Dubbo分布式日志追踪

很多互联网公司都用的dubbo分布式框架进行微服务的开发,一个大系统往往会被拆分成很多不同的子系统,并且子系统还会部署多台机器,当其中一个系统出问题了,查看日志十分麻烦

所以我们需要一个固定的流程ID和机器ip地址等来把所有的日志穿起来,当然可以通过调用其他接口时参数进行传递,但是这样子对代码的耦合性太强,对代码有侵入性。

我们可以通过dubbo的filter 结合slf4j的MDC或者log4j2的ThreadContext的进行参数的注入,可以直接在日志文件中配置被注入的参数,这样就对系统和日志id打印进行了解耦。

其中当用logback日志的时候是需要调用MDC的方法,而log4j2则需要调用ThreadContext的方法。

当然我们可以直接默认指定使用logback日志,当使用log4j2日志的时候,在启动虚拟机时候可以加载一个参数(-Dlogging.type=log4j2),然后通过System.getProperty(“logging.type”)获取出使用的日志类型进行判断,从而选择使用MDC还是ThreadContext。

上游系统调用下游系统和下游系统接收上游系统定义两个filter

@Activate(group = { Constants.CONSUMER })

@Activate(group = { Constants.PROVIDER })

下游系统被调用的时候可以通过dubbo中RpcContext的getAttachment方法来获取上游系统传递下来的值

String rid = RpcContext.getContext().getAttachment("TRACE_ID");

并且根据判断来使用MDC还是ThreadContext

String logType = System.getProperty("logging.type");

ThreadContext.put(key,val);
//或者
MDC.put(key, val);

result = invoker.invoke(invocation);

在方法调用完成后移除该ID

//放到try中
result = invoker.invoke(invocation);

//放在finally块中
ThreadContext.remove(key);
或者
MDC.remove(key);

当上游系统调用下游系统的时候,可以通过dubbo中RpcContext的setAttachment方法进行参数传递

RpcContext.getContext().setAttachment("TRACE_ID", id);
Result result = invoker.invoke(invocation);

以后只需要在dubbo工程中引入包,然后在resources的META-INF.dubbo的com.alibaba.dubbo.rpc.Filter文件中配置filter就行,然后在日志文件中用${trace_id} 即可获取打印日志id

当然如果想打印ip只需要使用com.alibaba.dubbo.common.utils.NetUtils工具获取ip,然后put到MDC或者ThreadContext里面

String ip = NetUtils.getLocalHost()

最后通过ELK对日志进行收集,到时候就能很快的定位到错误位置。当然也可以结合ElasticAlert进行错误日志报警。

注意:多线程的情况下,会取不到这个ID,需要自己做处理,比如将创建线程的时候将id通过参数传入(见:Dubbo分布式日志追踪,多线程不能获取窜ID和IP问题

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_20641565/article/details/78627202

猜你喜欢

转载自blog.csdn.net/varyall/article/details/81534301