本文主要讲解了spring cloud微服务使用Feign作为微服务间的通讯框架的情况下,如何使用统一的日志ID来追踪一次请求日志,高效排查日志。核心解决了以下问题:
1.代码无入侵
2.线程池(主/子线程)日志ID一致
3.日志ID传递到下游服务
(以下只提供了核心代码截图,详细代码可通过github、gitee仓库查看,文末附代码目录)
一、单体服务统一日志ID处理
MDC(Mapped Diagnostic Context,映射调试上下文)是log4j和logback提供的一种方便在多线程条件下记录日志的功能。MDC可以看成是一个与当前线程绑定的Map,可以往其中添加键值对。
1.创建一个MDC工具类MdcUtil
2.利用Filter在请求入口设置日志ID(如果是下游服务,可以从header获取到日志ID,否则生成新的日志ID)
3.使用logback的MDC机制日志模板中加入日志ID标识,取值方式为%X{trace-id}
4.使用postman请求API
【日志打印效果】16582427033635607为日志ID
22:58:23.365 [16582427033635607] [http-nio-6001-exec-3]INFO LogResponseBodyAdvice.beforeBodyWrite[32] - {"code":0,"message":"成功","data":"2022-07-19 22:58:23"}22:58:23.368 [16582427033635607] [http-nio-6001-exec-3]INFO RequestFilter.doFilterInternal[52] - GET 192.168.31.158 /api/time header:{"x-platform":"app"},param:{"a":"1"},body:{"b":"bb"},4ms
二、日志ID传递给线程池中的子线程
1.自定义线程池实现JDK的ThreadPoolExecutor,在提交任务的时候把日志ID绑定到Runnable一起提交,后续执行Runnable的run方法的时候可以通过成员变量的方式获取日志ID
三、微服务链路日志ID传递(基于Feign)
1.利用Feign提供的拦截器RequestInterceptor,在Feign请求发起前往RequestTemplate设置header就OK了
2.由于加入了Hystrix做熔断处理,需要解决Hystrix线程池(主/子线程)的日志ID传递,重写HystrixConcurrencyStrategy构建线程池的逻辑
【当前服务的日志】16582448303481157为日志ID
23:33:50.365 [16582448303481157] [hystrix-template-user-10]INFO FeignIPClient.execute[42] - 13ms GET http://192.168.31.158:8002/user/getById" />
【user服务的日志】16582448303481157为日志ID
23:33:50.363 [16582448303481157] [http-nio-8002-exec-3]INFO LogResponseBodyAdvice.beforeBodyWrite[32] - {"code":0,"message":"成功","data":{"id":1,"name":"adasd","status":2,"statusDesc":"冻结"}}23:33:50.366 [16582448303481157] [http-nio-8002-exec-3]INFO RequestFilter.doFilterInternal[52] - GET 192.168.31.158 /user/getById header:{"x-platform":"app"},param:{"id":"1"},body:{},6ms
怎么样?如果你觉得有用的话,还不快快搞起!!!
附:涉及的代码目录
github:GitHub - 897665787/springcloud-template
gitee:springcloud-template: 一个基于springcloud netflix微服务框架,记录了关于微服务开发的一些最佳应用,欢迎大家学习指导。
springcloud-template└── template-framework └── filter└── MdcFilter -- 对客户端请求添加MDC└── MdcUtil -- MDC工具 └── interceptor└── FeignHeaderInterceptor -- Feign调用过程中传递header值└── Transfer -- http请求线程与Hystrix线程 传输对象└── TransferHystrixConcurrencyStrategy -- Hystrix并发策略 └── threadpool└── CustomThreadPoolExecutor -- 自定义线程池 └── logback-conf-base.xml -- 基础日志配置
如果想了解如何高效收集请求/响应日志,可阅读我的文章
微服务分布式架构中,如何高效收集请求/响应日志_吾日三省Java的博客-CSDN博客