Spring Boot + Dubbo 框架下 日志链路追踪ID 的实现方案选型思路

suoniao 2020-10-15
需要:0索币

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

 

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

图片描述

全链路追踪的核心思想:

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

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

图片描述

 

二、方案选型

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)

Sleuth 是 Spring 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

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

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

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

 

2.3.2. 跨线程传递

解决 traceId 跨线程丢失问题

图片描述

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

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

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

需要使用 TtlRunnable 和 TtlCallable 来修饰传入线程池的 Runnable 和 Callable

 

2.3.3. 跨进程传递

解决 traceId 跨进程丢失问题

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

  • 服务消费者:负责传递链路追踪 ID
  • 服务提供者:负责接收 ID 并保存到 MDC 中

 

2.3.4. 总结

  • 优点:业务无入侵,最小依赖,扩展灵活,适配性强。

  • 缺点:需要自行实现,有大量的开发工作量。

 

三、方案总结

方案开发工作量可维护性入侵性性能
apm-toolkit业务无入侵
sleuth业务无入侵
自研业务无入侵


作者:zlt2000
链接:https://www.imooc.com/article/311029
来源:慕课网
本文首次发布于慕课网 ,转载请注明出处,谢谢合作

回帖
  • 消灭零回复
广告一下
程序员转型,副业赚钱教程
相关主题
Spring Boot + Dubbo 框架下 日志链路追踪ID 的实现方案选型思路 0
基于Dubbo实现简易分布式支付系统实战视频教程 0
Dubbo基础入门视频教程基础篇 0
基于阿里Dubbo的分布式架构系统设计视频教程 0
Dubbo入门到精通架构高级课程 0
SpringBoot阿里Dubbo打造分布式微服务版电影票购买系统 0
Qt实战分布式网盘系统实战Qt文件上传下载 0
Qt5实战教程之翻金币游戏开发 0
利用C++库QT实现秘钥分发系统 秘钥协商 校验 查看服务 0
最新C++入门到实战教程 c++实现计算器和QQ登录框 0
Qt开发物联网智能网关项目教程 0
Qt开发打地鼠游戏实战 QT学生管理系统实战教程 0
大龄程序员转型、程序员副业赚钱实战教程合集 0
程序员副业赚钱之抖音短视频制作实战教程 0
程序员副业赚钱之程序员投资赚钱实战教程 0
程序员副业赚钱之利用抖音短视频获取收入实战 0
程序员副业赚钱之抖音电商实战教程 0
程序员副业赚钱之利用豆瓣引流赚钱实战 0
程序员副业赚钱之抓住自媒体风口月入过万不是问题今日头条实战 0
程序员副业赚钱之靠搬运视频赚钱实战 0
相关主题
Qt实战分布式网盘系统实战Qt文件上传下载 0
Qt5实战教程之翻金币游戏开发 0
利用C++库QT实现秘钥分发系统 秘钥协商 校验 查看服务 0
最新C++入门到实战教程 c++实现计算器和QQ登录框 0
Qt开发物联网智能网关项目教程 0
Qt开发打地鼠游戏实战 QT学生管理系统实战教程 0
大龄程序员转型、程序员副业赚钱实战教程合集 0
程序员副业赚钱之抖音短视频制作实战教程 0
程序员副业赚钱之程序员投资赚钱实战教程 0
程序员副业赚钱之利用抖音短视频获取收入实战 0
程序员副业赚钱之抖音电商实战教程 0
程序员副业赚钱之利用豆瓣引流赚钱实战 0
程序员副业赚钱之抓住自媒体风口月入过万不是问题今日头条实战 0
程序员副业赚钱之靠搬运视频赚钱实战 0
程序员副业赚钱之靠写作技术文章实现收益 写作教程 0
程序员副业赚钱之利用知乎引流实现月入过万实战 0
程序员副业赚钱之利用个人IP打造月入5万项目 0
程序员副业赚钱之利用社群营销 打造躺赚个人号 0
程序员副业赚钱之靠运行公众号月入10万多哦 0
程序员副业赚钱之打造一个赚钱的快手号 0