网关给每个请求加了 X-Request-ID,同步接口的日志里能看到。异步任务里的日志全是 null,排查时只能靠时间猜是哪一次请求。第一次遇到会往复杂处想,其实漏掉的多是个小前提。
Map<String,String> ctx = MDC.getCopyOfContextMap();
executor.submit(() -> {
MDC.setContextMap(ctx);
try { work(); } finally { MDC.clear(); }
});
请求 ID 存在 ThreadLocal 或者请求上下文里,切换线程池执行异步任务时上下文没有一起带过去。MDC 是线程绑定的,新线程里自然是空的,任务里的日志就丢了这一段。这一点先确认清楚,后面就不用反复试。
「请求 ID 透传」这个问题文档写得含糊,实际行为以当前版本为准,别照旧版本的结论套。新版本先放一台机器上跑一天再全量,问题一般在这段时间暴露。
具体做法是,提交异步任务前把 MDC 的副本取出来 在任务里重新 put 回去;用包装过的线程池或 TaskDecorator 统一处理 别在每个任务里手写;任务结束时清理 MDC 避免线程复用时串号;用同一个 requestId 搜同步和异步两段日志 确认都能命中。
改完照着核一遍,异步任务日志里出现和入口相同的 requestId 用这个 ID 能串起同步和异步两段日志。
