Skip to content

链路传递原理

laziobird edited this page Feb 24, 2022 · 1 revision

链路数据如何传播

在Trace 传递中有一个核心的概念,叫Carrier(搬运工具)。它表示"搬运" Span中SpanContext 的工具。比方说Trace 为了把Span 信息传递下去,在HTTP调用场景中,会有HttpCarrier,在RPC 的调用场景中会有RpcCarrier 来搬运SpanContext。Trace 通过 Carrier可以把链路追踪状态从一个进程"搬运"到另一个进程里。

数据传播基本操作

为了更清晰看懂数据传播的过程,我们先了解Span 在传播中有的基本操作

  • StartSpan:Trace在具体操作中自动生成一个 Span
  • Inject 注入: 将Span 的SpanContext 写入到Carrier 的过程

链路数据为了进行网络传输,需要数据进行序列化和反序列化。这个过程Trace通过一个负责数据序列化反序列化上下文的Formatter接口实现的。例如在HttpCarrier使用中通常就会有一个对应的HttpFormatter。所以Inject 注入是委托给Formatter将SpanContext 进行序列化写入Carrier。
Formatter提供不同场景序列化的数据格式,叫做Format描述。比如:

  • Text Map: 基于字符串的Map记录 SpanContext 信息,适用RPC网络传输
  • HTTP Headers: 方便解析HTTP Headers信息,用于HTTP传输

一个Python程序实现Inject 注入过程,Formatter 序列化SpanContext成Text Map格式

##Trace 生成一个span
    tracer = Tracer()
    span = tracer.start_span(operation_name='test')
    tracer.inject(
        span_context=span.context,
        format=Format.TEXT_MAP,
        carrier=carrier)


  • Extract 提取: 将SpanContext 从Carrier 中Extract(提取出来)
span_ctx = tracer.extract(format=Format.TEXT_MAP, carrier={})

同理,从Carrier提取的过程也需要委托Formatter将SpanContext反序列化。

运行原理


图一:链路数据在HTTP传递
我们基于HTTP通信解释传播原理。由图一,这个过程大致分为两步:
1、发送端将 SpanContext 注入到请求中,相应伪代码实现

/**
** 将 SpanContext 中的 TraceId,SpanId,Baggage 等根据 format 参数注入到请求中(Carrier)
** carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
** err := Tracer.Inject(Span.Context(), opentracing.HTTPHeaders, carrier)
**/
Inject(sm SpanContext, format interface{}, carrier interface{}) error

2、接收端从请求中解析出 SpanContext,相应伪代码实现

// Inject() takes the `sm` SpanContext instance and injects it for
// propagation within `carrier`. The actual type of `carrier` depends on
/** 根据 format 参数从请求(Carrier)中解析出 SpanContext(包括 TraceId、SpanId、baggage)。
** 例如: 
**  carrier := opentracing.HTTPHeadersCarrier(httpReq.Header)
**  clientContext, err := Tracer.Extract(opentracing.HTTPHeaders, carrier)
**/
Extract(format interface{}, carrier interface{}) (SpanContext, error)

Carrier 负责将追踪状态从一个进程"Carry"(搬运)到另一个进程。对于一个 Carrier,如果已经被 Injected,那么它也可以被 Extracted(提取),从而得到一个SpanContext 实例。这个 SpanContext 代表着被 Injected 到 Carrier 的信息。

说到这里,你可能想知道这个Carrier 在HTTP中具体在哪。其实它就保存到HTTP的Headers中。而且,W3C组织为HTTP支持链路追踪专门在Headers 中定义了Trace 标准

https://www.w3.org/TR/trace-context/#trace-context-http-headers-format

W3C组织是对网络标准制定的一个非盈利组织,W3C是万维网联盟的缩写,像HTML、XHTML、CSS、XML的标准就是由W3C来定制

Clone this wiki locally