微服务透传日志traceId

server/2024/11/14 15:28:05/

问题

微服务架构中,一次业务执行完可能需要跨多个服务,这个时候,我们想看到业务完整的日志信息,就要从各个服务中获取,即便是使用了ELK把日志收集到一起,但如果不做处理,也是无法完整把一次业务请求的日志完整链路串联起来。有人说,可以在日志中加入某个业务参数,比如订单id等,但是不可能所有业务都是有这样的参数给你用的。

解决方案

在打印日志的时候加入一个可以贯穿整个业务请求的唯一标识,我们把它称traceId。下面是在一个物联网项目的微服务架构中,使用dubbo时的基本流程:
在这里插入图片描述
拿到traceId,该怎么使用呢?答案也很简单,用过logback的都知道,是可以在日志信息里配置一些公共参数的,比如方法名,类名,线程名等,我们把traceId也设置进去就可以了。
logback配置如下:

        <encoder class="ch.qos.logback.classic.encoder.PatternLayoutEncoder"><pattern>%date{yyyy-MM-dd HH:mm:ss} [%-5level]  [%X{traceId}]  [%thread] [%logger{80}] [%file:%line] [%method]>>>>>> %msg%n</pattern><charset>utf-8</charset></encoder>

代码中设置:
web过滤器,针对的是HTTP请求,

java">@Configuration
public class TraceFilter extends OncePerRequestFilter {@Overrideprotected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,FilterChain filterChain) throws IOException, ServletException {try {String uuid = UUID.randomUUID().toString();MDC.put("traceId",uuid);filterChain.doFilter(request, response);} finally {// 必须清除MDC.clear();}}
}

跨服务调用走dubbo:
消费者过滤器:

java">@Activate(group = {CommonConstants.CONSUMER})
public class ConsumerDubboFilter implements org.apache.dubbo.rpc.Filter{@Overridepublic Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {Map<String, Object> attachments = invocation.getObjectAttachments();// 获取traceIdString traceId = MDC.get("traceId");// 传递日志追踪信息attachments.put("traceId",traceId);return invoker.invoke(invocation);}
}

生产者过滤器:

java">@Activate(group = {CommonConstants.PROVIDER})
public class ProviderDubboFilter implements org.apache.dubbo.rpc.Filter{@Overridepublic Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {try {// 获取到traceIdString traceId = (String)invocation.getObjectAttachment("traceId");// 设置traceIdMDC.put("traceId",traceId);return invoker.invoke(invocation);}finally {// 必须清除MDC.clear();}}
}

有聪明的小伙伴,此时已经想到了一个问题,那就是如果在子线程中打印日志依然是拿不到traceId的,没关系,照样可以解决,子线程传递上下文信息,第一个想到的是什么?对,阿里的TTL,
在pom中引入:

        <dependency><groupId>com.ofpay</groupId><artifactId>logback-mdc-ttl</artifactId><version>1.0.2</version></dependency>

logback的xml配置中加入一行代码:

<contextListener class="com.ofpay.logback.TtlMdcListener"/>

还有伙伴会问,如果用的是OpenFeign呢,其实原理一样,使用OpenFeign的拦截器,在跨服务调用之前拦截,拿到traceId,再放入HTTP请求头中,下游服务在过滤器中再从请求头中获取即可。这里代码就不再展示,直接搜feign的拦截器使用就行了。

扩展

既然traceId可以这样透传,那么其他的一些公共的信息当然也可以透传,比如分页信息,用户信息,ThreadLocal中上下文信息,都可以使用这样的方式去透传,让开发人员感觉还是在单服务中一样简便。

下一篇:MQTT+Disruptor提高并发


http://www.ppmy.cn/server/141010.html

相关文章

GeoHash处理经纬度,降维,空间填充曲线

个人博客&#xff1a;无奈何杨&#xff08;wnhyang&#xff09; 个人语雀&#xff1a;wnhyang 共享语雀&#xff1a;在线知识共享 Github&#xff1a;wnhyang - Overview 参考 https://segmentfault.com/a/1190000042971576 GeoHash原理以及代码实现_geohash编码-CSDN博客…

NLP之ASR之moonshine:moonshine的简介、安装和使用方法、案例应用之详细攻略

NLP之ASR之moonshine&#xff1a;moonshine的简介、安装和使用方法、案例应用之详细攻略 目录 moonshine的简介 moonshine的安装和使用方法 1、安装 推荐使用uv管理Python环境 安装Moonshine包 Torch后端 TensorFlow后端 JAX后端 ONNX运行时 2、使用方法 0、测试 1…

Android下的系统调用 (syscall),内联汇编syscall

版权归作者所有&#xff0c;如有转发&#xff0c;请注明文章出处&#xff1a;https://cyrus-studio.github.io/blog/ 什么是系统调用 (syscall) 系统调用是操作系统提供给应用程序的一组接口&#xff0c;允许用户空间程序与内核进行交互。 在 Android&#xff08;基于 Linux …

华硕推出Intel Xeon 6/ Gaudi 3服务器 加速企业AI布局!

(10月23日&#xff0c;台北讯) 华硕服务器新品接力强势助攻&#xff0c;今再推出多款搭载Intel Xeon 6处理器的服务器&#xff0c;包括&#xff1a;多节点的ASUS RS920Q-E12&#xff0c;其兼容适用HPC运算的Intel Xeon 6900系列处理器&#xff1b;以及ASUS RS720Q-E12、RS720-E…

一篇文章解释AI中的“算力”与“数据”两个概念!

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言一、什么是算力?为什么算力重要?算力的发展历程什么是数据?数据的作用数据的应用场景算力与数据的关系总结前言 为什么我要特别讲这两个词呢?因为人工智能的核心其实就是三件事儿:算力、…

「QT」几何数据类 之 QPolygon 多边形类

✨博客主页何曾参静谧的博客&#x1f4cc;文章专栏「QT」QT5程序设计&#x1f4da;全部专栏「VS」Visual Studio「C/C」C/C程序设计「UG/NX」BlockUI集合「Win」Windows程序设计「DSA」数据结构与算法「UG/NX」NX二次开发「QT」QT5程序设计「File」数据文件格式「PK」Parasolid…

计算机的错误计算(一百五十)

摘要 探讨 MATLAB 中 的计算精度问题。当 为含有小数的大数或 &#xff08;&#xff09;附近数时&#xff0c;输出会有错误数字。 例1. 已知 计算 直接贴图吧&#xff1a; 另外&#xff0c;16位的正确值分别为 -0.7882256119904400e0、0.1702266977524110e0、-0.…

Redis的缓存问题与应对策略

Redis 作为一种高效的缓存系统&#xff0c;在高并发环境下应用广泛&#xff0c;但也面临一些缓存问题&#xff0c;以下是常见问题及其应对策略。 1. 缓存穿透 问题描述 缓存穿透是指请求的数据在缓存和数据库中都不存在&#xff0c;但大量请求直接到达数据库&#xff0c;从而给…