微服务的一次调用的日志信息分布在不同的机器上 ,当需要看一条链路调用所有的日志信息时, 通过生产一个本次唯一的链路Id(traceId)把一次请求的信息串起来。
为减少日志量 :切面日志可按需要添加
一 、 分布式追踪系统的思想模型:
二、选型
方案一:集成中间产品,如: Zipkin、SkyWalking等产品
优点:
无需编码
业务无入侵
图形化界面中使用该ID快速定位各种接口的调用关系
缺点:
强耦合中间件服务才能生
效必须添加相应 javaagent
必须部署服务端
方案二 集成 Spring Cloud sleuth
优点:业务无入侵,有丰富的插件进行扩展包括定时任务、MQ等。
缺点:brave-instrumentation-dubbo-rpc 不支持 dubbo 2.7.x 需要自行开发插件
方案三:自研, 集成 Logback
的 MDC
机制 (优先使用)
优点:
业务无入侵,最小依赖
自研,扩展灵活,适配性强
修改程序即可,无需部署其它中间件
缺点:
维护、升级需要有研发成本
三、这里推荐选择 方案三
思路及编码介绍(注意:本人用的 com.alibaba.dubbo ):
一次请求唯一 traceId 从网关层 到 服务(dubbo\springcloud)的消费者端 再到 服务的生产者端 透传,调用结束,清空traceId
1.公共类:
线程传递--ThreadTraceIdUtil
/**
* InheritableThreadLocal 线程传递
* @author Sjh
*/
public class ThreadTraceIdUtil {
/**使用InheritableThreadLocal便于在主子线程间传递参数*/
private static final ThreadLocal<String> TRACE_ID = new InheritableThreadLocal<>();
public ThreadTraceIdUtil() {
}
/**
* 从当前线程局部变量获取TraceId
* 首次调用该方法会生成traceId,后续每次都从线程上下文获取
* @return
*/
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();
}
}
生成 TraceId - TraceIdGenerator
/**
* @author Sjh
*
* 生成 TraceId
*/
@Slf4j
public class TraceIdGenerator {
/**
* 消费端创建TraceId,并设置到线程上下文中
* 该方法只调用一次
*
* @return
*/
public static String createTraceId() {
// 创建的同时就设置到上下文中
String traceId = getTraceId();
ThreadTraceIdUtil.setTraceId(traceId);
return traceId;
}
/**
* 生成32位traceId
*
* @return
*/
pri