近期在做甲方的项目里面用的技术体系很老非 spring boot项目是 jdk 8 spring spring mvc tomcat jsp 的方式在这里记录一下完整的处理过程。之前做的项目使用的是 spring cloud sleuth这边不让加一些其他依赖所以这个否决了鉴于后面线上排查问题方便不想翻全部日志考虑到之前在美团用的TraceId没用到spring cloud sleuth所以想看看是否有其他办法。请求发起是 http 然后通过 dubbo调用其他服务或者通过 http 再调用其他服务。使用的日志有logbacklog4j 1.x目前中有 slf4j这个日志门面所以就考虑到了 MDC 功能通过在 MDC 中加入 TraceId在日志中打印实现好定位。入口通常是页面发起请求如下TraceFilter.java/** * 请求过滤器添加TraceId到MDC中 */ Component public class TraceFilter extends OncePerRequestFilter implements Ordered { private static final Logger log LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); Override public int getOrder() { return Ordered.HIGHEST_PRECEDENCE; } Override protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain filterChain) throws ServletException, IOException { try { String traceId request.getHeader(TraceId); // 如果 http 请求头中没有 TraceId则生成一个否则使用请求头中的 TraceId if (StringUtils.isBlank(traceId)) { log.info(request header TraceId is blank); traceId UUID.randomUUID().toString(); } TraceIDUtils.setTraceId(traceId); MDC.put(TraceId, TraceIDUtils.getTraceId()); log.info(doFilterInternal start); filterChain.doFilter(request, response); } finally { TraceIDUtils.removeTraceId(); MDC.clear(); log.info(doFilterInternal finish); } } }调用完后记得清理 ThreadLocal 和 MDC不然会造成内存泄漏和数据污染。TraceIDUtils.javapublic class TraceIDUtils { private static final ThreadLocalString TRACE_ID new ThreadLocalString(); public static String getTraceId() { return TRACE_ID.get(); } public static void setTraceId(String traceId) { TRACE_ID.set(traceId); } public static void removeTraceId() { TRACE_ID.remove(); } }需要考虑到网络调用是其他服务发起的情况就是需要在http 发起调用时把 MDC 中的 TraceId 加入到请求头中就可以这样就能串联起来了。 添加如下代码HttpHeaders headers new HttpHeaders(); headers.add(TraceId, MDC.get(TraceId));日志把类的全路径和方法名还有代码行号都打印出来。logback配置%date [%thread] %X{logId} %-5level-[%X{TraceId}]-[%logger#%method:%line]-%msg%nlog4j 1.x配置[%d{yyyy-MM-dd HH:mm:ss SSS}]-[%t]-[%p]-[%X{TraceId}]-[%c#%M:%L]-%m%n这样就可以解决了单服务内调用的问题现在的问题是项目之间跨服务调用的使用了 dubbo所以做如下配置。rpcdubbo使用的是 dubbo 2.6.x版本在各自的项目中添加如下文件src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter需要声明生产者和消费者的过滤器如下消费者import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.common.extension.Activate; import com.alibaba.dubbo.rpc.Filter; import com.alibaba.dubbo.rpc.Invocation; import com.alibaba.dubbo.rpc.Invoker; import com.alibaba.dubbo.rpc.Result; import com.alibaba.dubbo.rpc.RpcContext; import com.alibaba.dubbo.rpc.RpcException; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import java.lang.invoke.MethodHandles; Activate(group Constants.CONSUMER) public class WebTraceConsumerFilter implements Filter { private static final Logger log LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private static final String TRACE_ID_KEY TraceId; Override public Result invoke(Invoker? invoker, Invocation invocation) throws RpcException { // 从当前线程的 MDC 中取出 TraceId String traceId MDC.get(TRACE_ID_KEY); // log.info(invoke traceId{}, traceId); if (StringUtils.isNotBlank(traceId)) { // 将 TraceId 设置到 Dubbo 的隐式参数Attachment中传递给服务端 // log.info(invoke set traceId into RpcContext traceId{}, traceId); RpcContext.getContext().setAttachment(TRACE_ID_KEY, traceId); } // log.info(invoke real invoke start traceId{}, traceId); Result invoke invoker.invoke(invocation); // log.info(invoke real invoke finish traceId{}, traceId); return invoke; } }配置文件中添加如下webTraceConsumerFilterxxx.filter.WebTraceConsumerFilter生产者import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.common.extension.Activate; import com.alibaba.dubbo.rpc.Filter; import com.alibaba.dubbo.rpc.Invocation; import com.alibaba.dubbo.rpc.Invoker; import com.alibaba.dubbo.rpc.Result; import com.alibaba.dubbo.rpc.RpcException; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.slf4j.MDC; import java.lang.invoke.MethodHandles; Activate(group Constants.PROVIDER) public class ServiceTraceProviderFilter implements Filter { private static final Logger log LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private static final String TRACE_ID_KEY TraceId; Override public Result invoke(Invoker? invoker, Invocation invocation) throws RpcException { // 1. 从 Dubbo 请求参数中获取由消费端传递的 TraceId String traceId invocation.getAttachment(TRACE_ID_KEY); // log.info(invoke remote traceId{}, traceId); // 2. 如果获取不到说明是直连请求或上游未传递此处可降级生成新ID或留空 if (StringUtils.isNotBlank(traceId)) { // log.info(invoke MDC.put traceId{}, traceId); MDC.put(TRACE_ID_KEY, traceId); } try { // log.info(invoke real invoke start traceId{}, traceId); // 3. 执行真正的业务逻辑 Result invoke invoker.invoke(invocation); // log.info(invoke real invoke finish traceId{}, traceId); return invoke; } finally { // log.info(invoke MDC.remove traceId{}, traceId); // 4. 清理 MDC防止内存泄漏或线程复用导致的下一个请求错乱 if (StringUtils.isNotBlank(traceId)) { MDC.remove(TRACE_ID_KEY); } } } }配置文件中添加如下serviceTraceProviderFilterxxx.filter.ServiceTraceProviderFilter最后项目启动后测试了一个跨服务调用包含 dubbo 、 http 调用的全链路日志打印正常通过 TraceId 精准匹配到对应的业务日志。
企业数字化 ERP 产品动态
相关推荐
冬季采暖选错设备,可能埋下安全隐患 冬季采暖选错设备,可能埋下安全隐患在北方严寒或工业高危环境中,普通电热设备一旦风机停转或电压不稳,极易过热起火。而巨恒PTC加热器凭借自限温、无明火、防干烧特性,成为汽车厂、化工车间、冷链园区的首选。本文将直接列出适配不… · 2026/9/23 23:54:26
opencloud+OpenCloudOS:AI助手的终极进化 🤯 试了 OpenCloudOS CubeSandbox 上的 OpenClaw,我直接回不去了
先交代背景:
用的 OpenCloudOS 9 CubeSandbox 环境
跑的是 OpenClaw 最新版本
体验了大概两周,说点真实的👇
🧠 先说说最惊喜的ÿ… · 2026/9/23 23:54:07
DeepSeek官宣峰谷计价,V4正式版7月中旬上线 大家好,我是搞自动化的大飞~昨天小编还在用DeepSeek API写代码,晚上就收到了计费调整通知,竟然涨价了DeepSeek也扛不住邮件里说了两件事:DeepSeek V4正式版要在7月中旬的时候上线了同时DeepSeek的价格变成动态收费了&a… · 2026/9/12 19:31:22
程序员戴耳机:不只是听歌,更是工位上的“安全气囊” 1. 从"摸鱼神器"到"生存刚需":耳机在程序员工位上的真正身份先说个我自己的经历。有次新来的实习生问我,是不是戴着耳机就听不见领导叫了,我说你观察挺准,但只说对了一半。后来他又问,是不是你们敲… · 2026/9/23 23:55:08
NC65高分屏字体放大补丁:Swing渲染链底层改造方案 简介:本资源是面向用友NC65系统开发与运维人员的高分屏显示适配补丁方案,专为解决Windows高分辨率屏幕下NC65界面字体过小、阅读困难等实际问题而设计。补丁基于JRE1.7编译,覆盖95%以上UI字体放大,并创新性加入打印场景过滤机制&a… · 2026/9/23 23:55:02
如何练就时尚眼光:从衣橱人口普查到风格签名档案 上周帮一个朋友整理衣橱,她站在爆满的衣柜前叹气:"我每次买衣服都觉得自己眼光不错,回来穿一次就闲置,是不是天生没有时尚细胞?"我当时的回答是:你先别急着买新衣服,你缺的根本不是审… · 2026/9/23 23:55:02
格拉布斯准则MATLAB代码:数据预处理异常值检测实战 简介:一套基于格拉布斯准则的异常数据判断代码,面向数学建模竞赛和美赛参赛者,用于解决数据预处理中的离群点检测问题。该准则通过计算样本最大值与均值的偏离程度,并与临界值比较,可有效识别正态分布数据中的极端值&a… · 2026/9/23 23:55:02
技术类博文标题的合规性与实操性判定标准 我不能根据该标题生成博文。原因如下:该标题涉及跨国媒体机构的商业决策与品牌变更事件(微软与NBC终止合作、MSNBC.com更名),属于新闻报道类事实性内容,而非可复现、可操作、可验证的“项目”;标题中无任何… · 2026/9/23 23:54:56
C++大型项目为何转向hpp单文件编译模式 1. 项目概述:为什么大型C项目开始“抛弃”cpp文件?在去年接手一个200万行代码的工业控制中间件重构时,我第一次被团队强制要求:所有新模块禁止新建.cpp文件,统一用.hpp和.h实现。当时我本能地皱眉——这不就是把实现塞… · 2026/9/23 23:54:56
3招搞定手机怎么下载微信面试难题实战项目解析 3招搞定手机怎么下载微信面试难题实战项目解析 面试被问“手机怎么下载微信”背后的原理,90%的人答不上来。别笑,这看似弱智的问题,实则是考察你对移动应用分发机制、安全校验及网络协议理解的试金石。我带过不少校招新人,他们背了八股文,却连一个A… · 2026/9/23 0:00:03
你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 你有新短消息请注意查收:3个新手避坑指南搞定消息系统选型 面试被问“高并发下如何保证消息不丢失”,你张口就是“用Redis”,结果面试官追问“如果Redis宕机了怎么办”,你瞬间卡壳。这种场景太常见了,很多新手在背八股文时,只记住了技术名词… · 2026/9/23 0:00:29