写点什么

有一说一! 项目中引进这玩意,排查日志又快又准

作者:程序员小毕
  • 2022-12-16
    湖南
  • 本文字数:4205 字

    阅读完需:约 14 分钟

有一说一!项目中引进这玩意,排查日志又快又准

背景

随着微服务盛行,很多公司都把系统按照业务边界拆成了很多微服务,在排错查日志的时候,因为业务链路贯穿着很多微服务节点,导致定位某个请求的日志以及上下游业务的日志会变得有些困难。

这时候可能有的小伙伴就会想到使用 SkyWalking,Pinpoint 等分布式追踪系统来解决,并且这些系统通常都是无侵入性的,同时也会提供相对友好的管理界面来进行链路 Span 的查询,但是搭建分布式追踪系统还是需要一定的成本的,所以本文要说的并不是这些分布式追踪系统,而是一款简单、易用、几乎零侵入、适合中小型公司使用的日志追踪框架 TLog。

TLog 简介

TLog 提供了一种最简单的方式来解决日志追踪问题,TLog 会自动的对你的日志进行打标签,帮你自动生成 traceId 贯穿你微服务的一整条链路,在排查日志的时候,可以根据 traceId 来快速定位请求处理的链路。

TLog 不收集日志,只在对你原来打印的日志上增强,将请求链路信息 traceId 绑定到你打印的日志上。当出现微服务中那么多节点的情况,官方推荐使用 TLog+日志收集方案来解决。当然分布式追踪系统其实是链路追踪一个最终的解决方案,如果项目中已经上了分布式追踪系统,那 TLog 并不适用。

如下图,是 ELK 配合 TLog,快速定位请求处理的链路的示例。

TLog 接入

1、接入步骤

1.1、引入依赖
<dependency>    <groupId>com.yomahub</groupId>    <artifactId>tlog-all-spring-boot-starter</artifactId>    <version>1.5.0</version></dependency>
复制代码
1.2、替换 logback 配置项

到这其实就已经完成了配置。

1.3、测试

这里是通过 slf4j 的 LoggerFactory 获取 Logger 对象,因为 logback 适配了 slf4j,最终会通过 logback 来输出日志。

从这可以看出,11794076298070144 就是本次日志输出的时候生成的一个请求的 traceId,在排查日志的时候就可以通过这个 traceId 去搜索出整个请求的链路日志。

2、TLog 接入方式

TLog 总共提供了三种方式接入项目

  • Javaagent 接入方式

  • 字节码注入方式

  • 日志框架适配器方式

上面案例的接入方式其实是属于日志框架适配器方式,并且是对于 Logback 框架的适配。TLog 除了适配了 Logback 框架,还适配了 Log4j 框架和 Log4j2 框架,项目中可自行选择。

Javaagent 接入方式和字节码注入方式相比与日志框架适配器方式对代码的入侵性更小,但是这两种方式仅仅只支持 SpringBoot 项目,并且相较于日志框架适配器的方式,MDC 和异步日志功能并不支持,所以要想完整体验 TLog 的功能,还是建议选择日志框架适配器方式,日志框架适配器方式其实接入也很快,其实也就是修改一下配置文件的事。

项目环境兼容对比

特性支持对比

TLog 的基本原理

1、日志标签

前面在介绍 TLog 的时候,提到 TLog 会自动的对你的日志进行打标签,这个标签就是日志标签,一个日志标签最多可以包含如下信息:

  • preApp:接口调用方服务名

  • preHost:接口调用方 Host

  • preIp:接口调用方 ip

  • currIp:当前服务 ip

  • traceId:链路 id,调用方如果传递就是传递的值,不传递就会重新生成

  • spanId:链路 spanId

默认是按照如下 labelPattern 进行数据拼接生成日志标签,所以默认只打出 spanId 和 traceId。

这也就是上面为什么示例中会输出 <0><11794076298070144> 这种格式的原因,前面的 0 其实就是 spanId。

如果你想改变日志标签输出其它信息或者输出的顺序,只需要在 SpringBoot 配置文件中配置日志标签的生成样式就行。

tlog.pattern=[$preApp][$preIp][$spanId][$traceId]
复制代码

2、TLogContext

TLogContext 是 TLog 是一个核心的组件,这个组件内部是使用了 TransmittableThreadLocal 来传递 traceId、preApp 等信息。

当有一个请求过来的时候,会从解析出 traceId、preApp 等信息,然后设置到 TransmittableThreadLocal 中,之后就可以在整个调用链路中从 TLogContext 中获取到 traceId 等信息。

3、TLogRPCHandler

这个组件是用来处理调用方传递的 traceId、preApp 等信息,设置到 TLogContext 和 MDC 中,同时根据日志标签的格式生成日志标签。

第三方框架的适配

在实际项目中,一个请求处理过程可能会出现以下情况

  • 异步线程处理

  • 跨服务调用

  • MQ 调用

那么对于这些情况来说,traceId 应该需要在异步线程、跨服务、MQ 等中传递,以便更好地排查一个请求的处理链路。

而 TLog 对于以上可能出现的情况都做了大量的适配,保证 traceId 能够在异步线程、微服务间、MQ 等中能够正确传递。

1、异步线程

1.1 一般异步线程

所谓的一般异步线程就是指直接通过 new Thread 的方法来创建异步线程,然后来执行,这种方式 TLog 是天然支持携带 traceId 的,如图。

执行结果

从这可以看出这种异步方式的确成功传递了 traceId。

1.2 线程池

对于线程池来说,其实默认也是支持传递 traceId,但是由于线程池中的线程是可以复用了,为了保证线程间的数据互不干扰,需要使用 TLogInheritableTask 将提交的任务进行包装。

ThreadPoolExecutor pool =        new ThreadPoolExecutor(1, 2, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10));pool.execute(new TLogInheritableTask() {    @Override    public void runTask() {      logger.info("异步执行");    }});
复制代码

上述代码的写法会有点耦合,每次提交任务都需要创建一个 TLogInheritableTask,比较麻烦,可以按如下写法进行简化。

TLogThreadPoolExecutor

自己写个 TLogThreadPoolExecutor 继承 ThreadPoolExecutor,重写 execute 方法(submit 最终也会调用 execute 方法执行),然后将提交的任务统一包装成 TLogInheritableTask,这样需要使用线程池的地方直接创建 TLogThreadPoolExecutor 就可以了,就不需要在提交任务的时候创建 TLogInheritableTask 了。

ThreadPoolExecutor pool =        new TLogThreadPoolExecutor(1, 2, 1, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10));pool.execute(() -> logger.info("异步执行"));
复制代码

2、对 RPC 框架的支持

除了对异步线程的支持,TLog 也支持常见的 Dubbo,Dubbox,OpenFeign 三大 RPC 框架,在 SpringBoot 项目中不需要任何配置,只需要引入依赖就可以实现 traceId 在服务之间的传递

2.1 对 Dubbo 和 Dubbox 的支持

对于 Dubbo 和 Dubbox 的支持是基于 Dubbo 的 Filter 扩展点来的

TLog 通过 SPI 机制扩展 Filter,在消费者发送请求前从 TLogContext 获取到 traceId,然后将 traceId 和其它调用者数据设置请求数据中,服务提供者在处理请求的时候,也会经过 Filter,从请求中获取到 traceId 等信息,然后设置到 TLogContext 中,从而实现了 traceId 在 dubbo 的消费者和提供者之间的传递。

2.2 对 OpenFeign 的支持

对于 OpenFeign 的支持其实也是通过 Feign 提供的扩展点 RequestInterceptor 来实现的

发送请求之前,从 TLogContext 获取到 traceId,将 traceId 等信息添加到请求头中,然后就可以通过 Http 请求将 traceId 等信息传递。

当被调用方接收到请求之后,会经过 TLogWebInterceptor 这个拦截器进行拦截,从请求头中获取到这些参数,设置到 TLogContext 中。

3、对常用 Http 框架的支持

除了一些 RPC 框架,TLog 也对一些 Http 框架进行了适配,比如

  • HttpClient

  • Okhttp

  • hutool-http

  • RestTemplate

  • forest

使用这些 Http 框架也可以实现 traceId 的传递

其实这些框架的适配跟 Feign 的适配都是大同小异,都是基于这些 Http 框架各自提供的扩展点进行适配的,将 traceId 等信息放到请求头中,这里都不举例了,具体的使用方法可以在官网查看。

4、对 SpringCloud Gateway 的支持

同样的,TLog 也适配了 SpringCloud Gateway

原理也是一样的,就是适配了 Gateway 的 GlobalFilter,从请求头中获取 traceId 等信息。

除了适配了 Gateway 网关,TLog 也适配了 Soul 网关。

5、对 MQ 的支持

对于 MQ 的支持跟异步线程差不多,需要将你发送的消息包装成 TLogMqWrapBean 对象

TLogMqWrapBean

发送的时候直接发送 TLogMqWrapBean 对象过去

TLogMqWrapBean<BizBean> tLogMqWrap = new TLogMqWrapBean(bizBean);mqClient.send(tLogMqWrap);
复制代码

TLogMqWrapBean 会将 traceId 等信息携带,消费者接受到 TLogMqWrapBean,然后通过 TLogMqConsumerProcessor 处理业务消息。

TLogMqConsumerProcessor.process(tLogMqWrapBean, new TLogMqRunner<BizBean>() {    @Override    public void mqConsume(BizBean o) {     //业务操作    }});
复制代码

如此就实现了 traceId 通过 MQ 传递。

在实际使用中,根据不同的 MQ 的类型,可以将消息包装成 TLogMqWrapBean 对象的过程和处理消息的过程做统一的封装处理,以减少发送消息和处理消息对于 TLog 的耦合。

6、对任务框架的支持

TLog 主要是支持一下四种任务框架

  • JDK Timer

  • Quartz 框架

  • spring-scheduled

  • XXL-JOB 框架

其中,spring-scheduled 和 XXL-JOB 在 SpringBoot 环境底下是无需任务配置的,只需要引入依赖即可。

Timer 在使用的时候需要将任务包装成 TLogTimerTask,Quartz 需要把 QuartzJobBean 替换成 TLogQuartzJobBean 就可以了。

小总结

其实从上面的各种适配可以看出,其实本质都是一样的,就是根据具体框架的扩展点,在发送请求之前从 TLogContext 获取到 traceId,将 traceId 等调用者的信息在请求中携带,然后被调用方解析请求,取出 traceId 和调用者信息,设置到被调用方服务中的 TLogContext 中。

所以,如果一旦需要遇到官方还未适配的框架或者组件,可以参照上述适配过程进行适配即可。

最后

总的来说,TLog 是一款非常优秀的日志追踪的框架,很适合中小公司使用。这里来总结一下 TLog 的特性

  • 通过对日志打标签完成轻量级微服务日志追踪

  • 提供三种接入方式:javaagent 完全无侵入接入,字节码一行代码接入,基于配置文件的接入

  • 对业务代码无侵入式设计,使用简单,10 分钟即可接入

  • 支持常见的 log4j,log4j2,logback 三大日志框架,并提供自动检测,完成适配

  • 支持 dubbo,dubbox,feign 三大 RPC 框架

  • 支持 Spring Cloud Gateway 和 Soul 网关

  • 支持 HttpClient 和 Okhttp 等 http 调用框架标签传递

  • 支持多种任务框架,JDK 的 TimerTask,Quartz,XXL-JOB,spring-scheduled

  • 支持日志标签的自定义模板的配置,提供多个系统级埋点标签的选择

  • 支持异步线程的追踪,包括线程池,多级异步线程等场景

  • 几乎无性能损耗,快速稳定,经过压测,损耗在 0.01%

由于本文篇幅有限,无法全面对 TLog 进行讲解,如果想深入了解该框架,可自行阅读官网或者源码。

官网:https://tlog.yomahub.com

github 地址:https://github.com/dromara/TLog

原文:https://mp.weixin.qq.com/s/gcjRN4baoEMEOwmpM5cXbw

如果感觉本文对你有帮助,点赞关注支持一下,想要了解更多 Java 后端,大数据,算法领域最新资讯可以关注我公众号【架构师老毕】私信 666 还可获取更多 Java 后端,大数据,算法 PDF+大厂最新面试题整理+视频精讲

用户头像

领取资料添加小助理vx:bjmsb2020 2020-12-19 加入

Java领域;架构知识;面试心得;互联网行业最新资讯

评论

发布
暂无评论
有一说一!项目中引进这玩意,排查日志又快又准_程序员_程序员小毕_InfoQ写作社区