首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Dubbo日志链路追踪TraceId选型

Dubbo日志链路追踪TraceId选型

原创
作者头像
陶陶技术笔记
修改2020-09-27 11:41:24
2.8K0
修改2020-09-27 11:41:24
举报
文章被收录于专栏:陶陶技术笔记陶陶技术笔记
封面.png
封面.png

一、目的

开发排查系统问题用得最多的手段就是查看系统日志,但是在分布式环境下使用日志定位问题还是比较麻烦,需要借助 全链路追踪ID 把上下文串联起来,本文主要分享基于 Spring Boot + Dubbo 框架下 日志链路追踪ID 的实现方案选型思路。

目前大多数分布式追踪系统的思想模型都来自 Google's Dapper 论文

depper.png
depper.png

全链路追踪的核心思想:

  • 为每条请求都单独分配一个唯一的 traceId 用来标识一条请求链路,该 traceId 会贯穿整个请求处理过程的所有服务
  • 每个服务/线程都拥有自己的 spanId 标识,代表请求的其中一段处理步骤
  • 一个请求包含一个 traceId 和一个或多个 spanId

日志全链路追踪 就是在每条系统日志里都添加显示 traceIdspanId 信息

日志链路追踪.png
日志链路追踪.png

二、方案选型

2.1. 方案一(apm-toolkit)

这是 SkyWalking 的一个日志插件,通过这个插件可以在日志中输出

traceId

2.1.1. 使用方式

配置依赖,在 pom 文件中添加以下内容

<dependency>
    <groupId>org.apache.skywalking</groupId>
    <artifactId>apm-toolkit-logback-1.x</artifactId>
    <version>8.1.0</version>
</dependency>

配置日志模板,修改 logback-spring.xml 文件中 Appender 元素的 encoder 为以下内容

<encoder class="ch.qos.logback.core.encoder.LayoutWrappingEncoder">
    <layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
        <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%tid] [%thread] %-5level %logger{35} - %msg%n</pattern>
    </layout>
</encoder>

ps: pattern 中的内容按需修改,其中的 %tid 就是相当于 traceId,默认 TID:N/A,当有请求调用时会生成并显示 traceId

2.1.2. 总结
  • 优点:无需编码,业务无入侵,可与 SkyWalking 的图形化界面中使用该ID快速定位各种接口的调用关系。
  • 缺点:强耦合 SkyWalking 才能生效
    • 必须添加sk的 javaagent
    • 必须部署 SkyWalking 服务端

2.2. 方案二(sleuth)

SleuthSpring Cloud 的组件之一,它为 Spring Cloud 实现了一种分布式追踪解决方案,兼容Zipkin,HTrace与其他日志追踪系统

2.2.1. 使用方式

配置父依赖,在 pom 文件中添加以下内容管理版本号

<dependencyManagement>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-sleuth</artifactId>
            <version>2.2.4.RELEASE</version>
            <type>pom</type>
            <scope>import</scope>
        </dependency>
</dependencyManagement>

配置依赖,在 pom 文件中添加以下内容

<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-sleuth</artifactId>
</dependency>

适配dubbo,要让 sleuth 支持 dubbo 框架,需要增加以下两个步骤:

首先添加 dubbo 的插件依赖

<dependency>
    <groupId>io.zipkin.brave</groupId>
    <artifactId>brave-instrumentation-dubbo-rpc</artifactId>
    <version>5.12.6</version>
</dependency>

配置 dubbo 过滤器

dubbo:
  provider:
    filter: tracing
  consumer:
    filter: tracing

配置日志模板,修改 logback-spring.xml 文件中 Appender 元素的 encoder 为以下内容

<encoder>
    <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} [%X{X-B3-TraceId},%X{X-B3-SpanId}] [%thread] %-5level %logger{35} - %msg%n</pattern>
    <charset>utf-8</charset>
</encoder>

ps: pattern 中的内容按需修改,其中的 %X{X-B3-TraceId} 为 traceId,%X{X-B3-SpanId} 为 spanId

2.2.2. 总结
  • 优点:业务无入侵,有丰富的插件进行扩展包括定时任务、MQ等。
  • 缺点brave-instrumentation-dubbo-rpc 不支持 dubbo 2.7.x 需要自行开发插件。

2.3. 方案三(自研)

2.3.1. 无入侵增加 traceId

使用 LogbackMDC 机制,在日志模板中加入 traceId 标识,取值方式为 %X{traceId}

  1. 系统入口(api网关)创建 traceId 的值
  2. 使用 MDC 保存 traceId
  3. 修改 logback 配置文件模板格式添加标识 %X{traceId}

MDC(Mapped Diagnostic Context,映射调试上下文)是 log4j 和 logback 提供的一种方便在多线程条件下记录日志的功能。

2.3.2. 跨线程传递

解决 traceId 跨线程丢失问题

mdc源码.png
mdc源码.png

由于 MDC 内部使用的是 ThreadLocal 所以只有本线程才有效,子线程和下游的服务 MDC 里的值会丢失;

需要解决 Spring 的各种线程池与异步方法的父子线程间传递。

解决思路:重写一个 MDCAdapter 使用阿里的 TransmittableThreadLocal 替换原来的 ThreadLocal 对象,解决各种线程池(ExecutorService / ForkJoinPool / TimerTask)父子进程传值问题。

需要使用 TtlRunnableTtlCallable 来修饰传入线程池的 RunnableCallable

2.3.3. 跨进程传递

解决 traceId 跨进程丢失问题

dubbo服务 使用 org.apache.dubbo.rpc.Filter 创建一个过滤器进行 traceId 传递

  • 服务消费者:负责传递链路追踪 ID
  • 服务提供者:负责接收 ID 并保存到 MDC
2.3.4. 总结
  • 优点:业务无入侵,最小依赖,扩展灵活,适配性强。
  • 缺点:需要自行实现,有大量的开发工作量。

三、方案总结

方案

开发工作量

可维护性

入侵性

性能

apm-toolkit

业务无入侵

sleuth

业务无入侵

自研

业务无入侵

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、目的
  • 二、方案选型
    • 2.1. 方案一(apm-toolkit)
      • 2.1.1. 使用方式
      • 2.1.2. 总结
    • 2.2. 方案二(sleuth)
      • 2.2.1. 使用方式
      • 2.2.2. 总结
    • 2.3. 方案三(自研)
      • 2.3.1. 无入侵增加 traceId
      • 2.3.2. 跨线程传递
      • 2.3.3. 跨进程传递
      • 2.3.4. 总结
  • 三、方案总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档