这篇文章给大家聊聊关于微服务日志链路追踪实践,以及对应的知识点,希望对各位有所帮助,不要忘了收藏本站哦。
最近想在项目中添加一个简单的分布式请求跟踪功能,从前端向网关发起请求,然后从网关调用Spring Cloud的微服务。在这些过程中,我希望从日志中看到一个分布式的ID链接,通过请求的ID可以追踪整个链接,方便排查问题。
[[378163]]
现成的解决方案自然是使用SkyWalking、Spring Cloud Sleuth、Zipkin等组件。但考虑到主要目的是记录一个可以在整个每个服务中使用的ID,以方便日志查询,所以不想引入太多复杂的组件,最终决定通过MDC在日志中输出追踪到的ID,以及然后在Feign和RestTemplate中传递微服务中的请求ID。
主要包括几个步骤:
前端生成请求ID,并将请求头添加到网关。通过WebFilter拦截并添加到MDC中。将其输出到日志中。将请求ID放入Feign和RequestTemplate中,并带到HTTP的头部。微服务交付。每个微服务也是通过WebFilter来实现的。拦截并添加MDC,并在日志中输出MDC。 MDC(Mapped Diagnostic Context,映射调试上下文)是Log4j和Logback提供的功能,方便多线程情况下进行日志记录。 MDC可以看成是绑定到当前线程的哈希表,可以向其中添加键值对。
MDC的关键操作:
将值设置为MDC:MDC.put(key, value);从MDC获取值:MDC.get(key);将MDC的内容打印到日志中:%X{key}新增 TraceId 工具类首先添加一个TraceIdUtils工具类,用于定义TRACE_ID的常量值以及设置和生成TRACE_ID的方法。后续所有的代码操作都是通过这个估计类来进行的。
importorg.apache.commons.lang.RandomStringUtils;importorg.apache.commons.lang.StringUtils;importorg.slf4j.MDC;publicclassTraceIdUtils{publicstaticfinalStringTRACE_ID='traceId';privatestaticfinalintMAX_ID_LENGTH=10;/***生成traceId*/privatestaticStringgenTraceId(){ returnRandomStringUtils.randomAlphanumeric(MAX_ID_LENGTH);}/***设置traceId*/publicstaticvoidsetTraceId(StringtraceId){//如果参数为空则生成新的IDtraceId=StringUtils.isBlank(traceId)?genTraceId():traceId;//放入traceId前往MDC MDC.put(TRACE_ID,StringUtils.substring(traceId,-MAX_ID_LENGTH));}/***获取traceId*/publicstaticStringgetTraceId(){//获取StringtraceId=MDC.get(TRACE_ID);//如果traceId为空的话,生成一个新的ID returnStringUtils.isBlank(traceId)?genTraceId():traceId;}}通过 WebFilter 添加 TraceId 过滤器添加GenericFilterBean,从请求头中获取TraceIdUtils.TRACE_ID对应的值。该值在前端发起请求时或者微服务之间使用。将被传递,如果没有,TraceIdUtils.setTraceId 将生成一个。
importorg.springframework.core.annotation.Order;importorg.springframework.web.filter.GenericFilterBean;@WebFilter(urlPatterns='/*',filterName='traceIdFilter')Order(1)publicclassTraceIdFilterextendsGenericFilterBean{@OverridepublicvoiddoFilter(ServletRequestrequest,ServletResponseresponse,FilterChainfil terChain ; }不要忘记添加@ServletComponentScan注解到SpringBoot启动类,否则自定义的Filter不会生效其中“com.yourtion.trace.filter”为TraceIdFilter所在的包名。
@ServletComponentScan(basePackages='com.yourtion.trace.filter')@SpringBootApplicationpublicclassMyApplication{publicstaticvoidmain(String[]args){SpringApplication.run(MyApplication.class,args);}}在 Feign 上添加 TraceId因为@FeignClient的代理类是执行时,您将使用使用Spring上下文的RequestInterceptor,因此您自定义自己的拦截器,然后将其注入到Spring上下文中,这样您就可以在请求上下文中添加自定义请求头。
导入feign.requestInterceptor;导入feign.requestTemplate; Importorg.s PlementsRequestInterceptor {@OverridePublicvoidApply(RequestTemplateTemplate){template.header(traceidutils.trace_id,traceidutils.get Traceid());}}在 RestTemplate 上添加 TraceId和部分请求是通过RestTemplate 发起的。之前我们自己实现了RestTemplateConfig的配置类。这次我们在相关配置中添加了以下内容:
RestTemplaterestTemplate=builder.additionalInterceptors((request,body,execution)-{request.getHeaders().add(TraceIdUtils.TRACE_ID,TraceIdUtils.getTraceId());returnexecution.execute(request,body);}).build();至此,链接上TraceId的添加已经完成,剩下的就是在日志中打印出来了。
修改Log4j2的布局格式
修改日志的布局格式,打印出MDC中的traceId:
--原始格式--'%5p%c:%L-%m%throwable{separator(--)}%n'/--增加traceId的格式--'%5ptraceId:%X{traceId}%c:%L - %m%throwable{separator(--)}%n'/至此,修改完成。
好了,本文到此结束,如果可以帮助到大家,还望关注本站哦!
本文采摘于网络,不代表本站立场,转载联系作者并注明出处:https://www.iotsj.com//kuaixun/6756.html
用户评论
这篇文章让我对微服务架构下的日志追踪有了新的理解!
有7位网友表示赞同!
感觉链路追踪技术对于微服务系统非常重要,能帮助定位问题真是太棒了。
有5位网友表示赞同!
想了解一下这个分布式日志追踪是如何实现的,细节方面会不会在文章里讲到?
有18位网友表示赞同!
最近一直在研究微服务架构,这篇文章正好是我现在需要的内容!
有12位网友表示赞同!
分布式追踪的难点在哪里?有人可以分享下吗?
有10位网友表示赞同!
我之前用的都是集中式的日志处理系统,对微服务的分布式系统还不太熟悉。
有14位网友表示赞同!
学习微服务,日志链路追踪必不可少啊!期待看到详细介绍。
有15位网友表示赞同!
希望这篇文章能给出一些具体的技术方案和案例,方便参考学习。
有19位网友表示赞同!
微服务部署越来越常见了,分布式日志追踪真是个很实用的技术。
有10位网友表示赞同!
简单易懂的介绍,太好了!这样我就能快速入门微服务日志链路追踪了。
有15位网友表示赞同!
这篇文章正好可以帮我解决一下现在项目里遇到的微服务日志问题!
有13位网友表示赞同!
分布式系统下的日志管理确实很复杂,期待作者能给出一些可行的解决方案。
有16位网友表示赞同!
对于不同类型的微服务应用,链路追踪的需求会不一样吗? 文章里有提到吗?
有9位网友表示赞同!
我已经开始搭建微服务架构了,这篇文章刚好可以帮助我完善系统的设计。
有14位网友表示赞同!
学习一下分布式日志追踪技术,能够提高项目开发和维护效率啊!
有10位网友表示赞同!
希望这篇文章能提供一些常用的工具和平台,方便我们快速进行链路追踪部署。
有8位网友表示赞同!
微服务架构的日志管理很有学问,感谢作者分享这方面经验!
有9位网友表示赞同!
感觉学习分布式日志追踪技术对我的职业发展很有帮助!
有19位网友表示赞同!
看了标题之后,我已经迫不及待想看看这篇文章的内容了!
有8位网友表示赞同!
希望这篇文章能够清晰地讲解分布式日志追踪的步骤和方法。
有11位网友表示赞同!