Dubbo分布式日志追踪 浅浅的花香味﹌ 2021-12-23 12:11 204阅读 0赞 使用[dubbo][]分布式框架进行微服务的开发,一个大系统往往会被拆分成很多不同的子系统,并且子系统还会部署多台机器,当其中一个系统出问题了,查看日志十分麻烦。 所以需要一个固定的流程ID和机器ip地址等来把所有的日志进行染色处理,当然可以通过调用其他接口时参数进行传递,但是这样子对代码的耦合性太强,对代码有侵入性。 我们可以通过dubbo的filter 结合slf4j的MDC或者log4j2的ThreadContext的进行参数的注入,可以直接在日志文件中配置被注入的参数,这样就对系统和日志id打印进行了解耦。 其中当用logback日志的时候是需要调用MDC的方法,而log4j2则需要调用ThreadContext的方法。 下面的例子是使用slf4j的日志模式: 1.上游系统调用下游系统和下游系统接收上游系统定义两个filter ProviderRpcTraceFilter(生产者) import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.common.extension.Activate; import com.alibaba.dubbo.rpc.*; import org.apache.commons.lang3.StringUtils; import org.slf4j.MDC; /** * 日志染色 * @author phpdragon */ @Activate(group = {Constants.PROVIDER},order = 1) public class ProviderRpcTraceFilter implements Filter { /** * * @param invoker * @param invocation * @return * @throws RpcException */ @Override public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { String traceId = RpcContext.getContext().getAttachment("trace_id"); if (StringUtils.isBlank(traceId)) { traceId = this.getUUID() ; } //设置日志traceId变量 MDC.put("traceId", traceId); RpcContext.getContext().setAttachment("trace_id", traceId); try{ return invoker.invoke(invocation); }finally { MDC.remove("traceId"); } } /** * 获取UUID * @return String UUID */ public String getUUID(){ String uuid = UUID.randomUUID().toString(); //替换-字符 return uuid.replaceAll("-", ""); } } ConsumerRpcTraceFilter(消费者) import com.alibaba.dubbo.common.Constants; import com.alibaba.dubbo.common.extension.Activate; import com.alibaba.dubbo.rpc.*; import org.apache.commons.lang3.StringUtils; import org.slf4j.MDC; /** * 日志染色ProviderRpcTraceFilter * @author phpdragon */ @Activate(group = {Constants.CONSUMER}) public class ConsumerRpcTraceFilter implements Filter { /** * * @param invoker * @param invocation * @return * @throws RpcException */ @Override public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException { String traceId = MDC.get("traceId"); if (StringUtils.isBlank(traceId)) { traceId = this.getUUID() ; } RpcContext.getContext().setAttachment("trace_id", traceId); return invoker.invoke(invocation); } /** * 获取UUID * @return String UUID */ public String getUUID(){ String uuid = UUID.randomUUID().toString(); //替换-字符 return uuid.replaceAll("-", ""); } } 2.下游系统被调用的时候可以通过dubbo中RpcContext.getAttachment()方法来获取上游系统传递下来的值 String traceId = RpcContext.getContext().getAttachment("trace_id"); 3.使用MDC来设置日志变量 %X\{traceId\} MDC.put("traceId", traceId); 4.在方法调用完成后移除该ID try{ return invoker.invoke(invocation); }finally { MDC.remove("traceId"); } 5.当上游系统调用下游系统的时候,可以通过dubbo中RpcContext.setAttachment()方法进行参数传递 RpcContext.getContext().setAttachment("trace_id", traceId); 6.然后在/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter (或者 com.apache.dubbo.rpc.Filter ) 文件中配置filter providerRpcTraceFilter=com.xxx.xxx.filter.ProviderRpcTraceFilter consumerRpcTraceFilter=com.xxx.xxx.filter.ConsumerRpcTraceFilter ![1131617-20190404131949435-1321518726.png][] 7.如果要打印服务器ip,使用com.alibaba.dubbo.common.utils.NetUtils工具获取ip,然后put到MDC里面 String serverIp = NetUtils.getLocalHost() MDC.put("serverId", serverIp); 8.设置logback.xml 的日志输出格式 %d{yyyy-MM-dd HH:mm:ss.SSS} [%X{traceId}] [%X{serverId}] [%X{sessionId}] -%5p ${PID:-} [%15.15t] %-40.40logger{39} : %m%n 注意: **1. dubbo应用同时担任provider、consumer时,RpcTraceFilter 不能合并成一个类,必须分开。** 2.多线程的情况下,会取不到这个ID,需要做处理,比如将创建线程的时候将id通过参数传入(见:[https://blog.csdn.net/qq\_20641565/article/details/78628115][https_blog.csdn.net_qq_20641565_article_details_78628115]) 转载于:https://www.cnblogs.com/wangjing666/p/10654308.html [dubbo]: https://www.baidu.com/s?wd=dubbo&tn=24004469_oem_dg&rsv_dl=gh_pl_sl_csd [1131617-20190404131949435-1321518726.png]: /images/20211223/c209ff37ca754753a5be934c022ffcbd.png [https_blog.csdn.net_qq_20641565_article_details_78628115]: https://blog.csdn.net/qq_20641565/article/details/78628115
还没有评论,来说两句吧...