跟踪:跟踪是跟随一个事物或一个请求从开始到结束的整体生命周期的过程,包括其所流经的组件。

分布式跟踪是跟踪和分析分布式系统中所有服务中的请求或事物发生的情况的过程。

分布式跟踪的方式:

基于模式、黑盒接口、无数据传播

分布式跟踪系统:

        DT是指在分布式系统中跟踪一个用户请求的过程,它包括数据采集、数据传输、数据存储、数据分析和数据可视化等,而捕获此类跟踪构建用户交互背后的整个调用链的视图是调试和监控微服务的关键工具。

分布式跟踪的实现方式:

大多数端到端跟踪的基础架构都会使用如下三种方法之一来识别与因果相关的活动:

        基于模式( Schema-based):通过开发人员编写时间连接模式以建立变量之间的因果关系,并通过自定义编写的日志消息予以公开;

可视作手动跟踪机制;

与采样机制不兼容, 因为在收集所有日志之前, 他们会延迟确定因果关系;

        黑盒接口( Blackbox Interface):不侵入应用程序, 它基于关联预先存在的变量和时间通过统计或回归分析来推断因果关系;

显然, 它无法正确地解释异步( 缓存或事件驱动的系统) 行为、 并发、 聚合以及专有的代码模式;

        元数据传播( Metadata Propagation) :这是谷歌关于Dapper的研究论文中所采用的方法许多实现被设计用于白盒系统, 它通过修改组件以传播描述因果活动相关的元数据( 例如ID等)

        所有基于元数据传播的实现都可以识别单个函数或跟踪点之间的因果关系,并以日志记录的形式记录相关时间内的事件从本质上讲,手动对组件在特定的跟踪点添加检测机制以跟踪函数、组件和系统之间的因果关系;另外,也可使用通用的RPC库,自动为每个调用添加元数据;

        跟踪的元数据包括Trace ID( 代表单个跟踪或工作流) 和特定跟踪中每个点的Span ID( 例如, 从客户端发送的请求、 服务器接收的请求、 服务器响应等) 以及Span的开始和结束时间;

        有最好时效性的分布式跟踪机制;

跟踪模型:

image.png

端到端跟踪系统架构:

image.png

分布式跟踪框架:

OpenTracing:是一个Library,定义了一套通用的数据上报接口,应用只要对接OpenTracing无需关系后端采用什么分布式追踪系统。

OpenCensus:由Google开源的一个用来收集和追踪应用指标的第三方库提供了一套统一的测量工具:跨服务捕获跟踪span、应用级别指标以及来自其他应用的元数据( 例如日志)它将自己定义为更多的可观察性框架,而不仅仅是跟踪。

OpenTelemetry:是上面两个库的优点合并的新项目。OpenCensus同OpenTracing用例和用途方面有很多重叠,但它们在API理念和方法方面有所不同,甚至是不相兼容,避免社区分裂所以合并。

自托管分布式跟踪系统:

Zipkin:由Twitter基于Dapper论文实现的开源分布式追踪系统, 通过收集分布式服务执行时间的信息来达到追踪服务调用链路、以及分析服务执行延迟等目的;架构组件

    collector: 信息收集器守护进程

    storage: 存储组件

    API: search API查询进程

    web UI: 用户界面

Jaeger:由Uber实现的一款开源分布式追踪系统,兼容OpenTracing API


配置Envoy的分布式跟踪机制:

Envoy用三个功能来支撑系统范围内的跟踪:

        生成请求ID: Envoy 会在需要的时候生成UUID, 并填充x-request-id HTTP标头, 应用可以转发这个标头以进行统一的记录和跟踪;

        集成外部跟踪服务: Envoy支持可插接的外部跟踪可视化服务, 包括LightStep、 Zipkin 或者 Zipkin 兼容的后端( 例如 Jaeger) ;

        加入客户端跟踪ID: x-client-trace-id标头可以用来把不受信的请求ID连接到受信的xrequest-id标头;

处理请求的HTTP连接管理器必须设置跟踪对象, 有多种途径可以初始化跟踪:

        外部客户端,使用x-client-trace-id

        内部服务,使用x-envoy-force-trace

        随机采样使用运行时设置random_sampling

路由过滤器可以使用start_child_span来为egress调用创建子Span;


配置Envoy的跟踪机制:

目前,Envoy仅支持HTTP协议的跟踪器;

在Envoy配置跟踪机制通常由三部分组成

        定义分布式跟踪系统相关的集群将使用的Zipkin或Jaeger等分布式跟踪系统定义为Envoy可识别的集群;

        定义在clusters配置段中,需要静态指定;

tracing{}配置段;

        Envoy使用的跟踪器的全局设定

        通常应该由Bootstrap配置在顶级配置段定义;

在http_connection_manager上启用tracing

        用于定义是否向配置的跟踪系统发送跟踪数据

static_resources:
  listeners:
  - name: ...
    address: {...}
    filter_chains:
    - filters:
    - name: envoy.http_connection_manager
      stat_prefix: ...
      route_config: {...}
      tracing: {...} # 发送跟踪数据;
    ...
  clusters:
  - name: zipkin|jaeger|...
    ...
	
tracing: {...} # Envoy使用的跟踪器的全局设定;
  http: {...} # HTTP跟踪器;

Envoy跟踪的全局配置, 以Zipkin为例( Jaeger兼容):

tracing:
  http:
    name: ...
    typed_config:
      "@type": type.googleapis.com/envoy.config.trace.v2.ZipkinConfig
      collector_cluster: ... # 指定承载Zipkin收集器的集群名称, 该集群必须在Bootstrap静态集群资源中定义;
      collector_endpoint: ... # Zipkin服务的用于接收Span数据的API端点; Zipkin的标准配置, 其API端点为/api/v1/spans;
      trace_id_128bit: ... # 是否创建128位的跟踪ID, 默认为false, 即使用64位的ID;
      shared_span_context: ... # 客户端和服务器Span是否共享相同的span id, 默认为true;

在http_connection_manager中发送跟踪数据:

filter_chains:
  - filters:
    - name: envoy.http_connection_manager
      stat_prefix: ...
      route_config: {...}
      tracing:
        operation_name: ... # 操作名称, 用于派生span的名称; 可用取值INGRESS( 默认) 和EGRESS, 分别用于ingress和egress类型的侦听器;
        request_headers_for_tags: [] # 用于为活动span创建tag的标头名称列表, 其中标头名称将用于tag名称, 而标头值则用于tag值;
    请求报文中存在指定的标头时, 则将其创建为tag;
        client_sampling: ... #
        random_sampling: ... #
        overall_sampling: ... #
        verbose: ... # 是否为span标注额外信息, 设定为true时, 则span将包含stream事件的日志信息;


配置示例: zipkin


Enovy分布式跟踪机制的启用需要三处关键配置

1、在所有Envoy的HTTP connection manager中启用跟踪功能以收集请求跟踪

- filters:
  - name: envoy.http_connection_manager
  config:
    tracing:
      operation_name: egress

2、启用Span传播机制, 收集跟踪数据至zipkin集群

tracing:
  http:
    name: envoy.zipkin
    config:
      collector_cluster: zipkin
      collector_endpoint: "/api/v1/spans"
...
static_resources:
...
  clusters:
  - name: zipkin
    connect_timeout: 1s
    type: strict_dns
    lb_policy: round_robin
    load_assignment:
      cluster_name: zipkin
      endpoints:
      - lb_endpoints:
        - endpoint:
            address: { socket_address: { address: zipkin, port_value: 9411 } }

3、应用程序传播由Enovy生成的跟踪标头。

TRACE_HEADERS_TO_PROPAGATE = [
    'X-Ot-Span-Context',
    'X-Request-Id',
    # Zipkin headers
    'X-B3-TraceId',
    'X-B3-SpanId',
    'X-B3-ParentSpanId',
    'X-B3-Sampled',
    'X-B3-Flags',
    # Jaeger header (for native client)
    "uber-trace-id"
]


配置示例: jaeger


1、在HTTP connection manager启用跟踪功能。

- filters:
  - name: envoy.http_connection_manager
    config:
      generate_request_id: true
      tracing:
        operation_name: egress

2、启用Span传播机制, 收集跟踪数据至jaeger集群。

tracing:
  http:
    name: envoy.zipkin
    typed_config:
      "@type": type.googleapis.com/envoy.config.trace.v2.ZipkinConfig
      collector_cluster: jaeger
      collector_endpoint: "/api/v1/spans"
      shared_span_context: false
...
static_resources:
...
  clusters:
  - name: jaeger
    connect_timeout: 1s
    type: strict_dns
    lb_policy: round_robin
    load_assignment:
      cluster_name: jaeger
      endpoints:
      - lb_endpoints:
        - endpoint:
            address: { socket_address: { address: jaeger, port_value: 9411 }}