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

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

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

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

下面的例子是使用slf4j的日志模式:

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

ProviderRpcTraceFilter

  1. import com.alibaba.dubbo.common.Constants;
  2. import com.alibaba.dubbo.common.extension.Activate;
  3. import com.alibaba.dubbo.rpc.*;
  4. import org.apache.commons.lang3.StringUtils;
  5. import org.slf4j.MDC;
  6.  
  7. /**
  8. * 日志染色
  9. * @author phpdragon
  10. */
  11. @Activate(group = {Constants.PROVIDER},order = 1)
  12. public class ProviderRpcTraceFilter extends Filter {
  13.  
  14. /**
  15. *
  16. * @param invoker
  17. * @param invocation
  18. * @return
  19. * @throws RpcException
  20. */
  21. @Override
  22. public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
  23. String traceId = RpcContext.getContext().getAttachment("trace_id");
  24. if (StringUtils.isBlank(traceId)) {
  25. traceId = this.getUUID() ;
  26. }
  27.  
  28. //设置日志traceId变量
  29. MDC.put("traceId", traceId);
  30.  
  31. RpcContext.getContext().setAttachment("trace_id", traceId);
  32.  
  33. try{
  34. return invoker.invoke(invocation);
  35. }finally {
  36. MDC.remove("traceId");
  37. }
  38. }
  39.  
  40. /**
  41. * 获取UUID
  42. * @return String UUID
  43. */
  44. public String getUUID(){
  45. String uuid = UUID.randomUUID().toString();
  46. //替换-字符
  47. return uuid.replaceAll("-", "");
  48. }
  49.  
  50. }

ConsumerRpcTraceFilter

  1. import com.alibaba.dubbo.common.Constants;
  2. import com.alibaba.dubbo.common.extension.Activate;
  3. import com.alibaba.dubbo.rpc.*;
  4. import org.apache.commons.lang3.StringUtils;
  5. import org.slf4j.MDC;
  6.  
  7. /**
  8. * 日志染色ProviderRpcTraceFilter
  9. * @author phpdragon
  10. */
  11. @Activate(group = {Constants.CONSUMER})
  12. public class ConsumerRpcTraceFilter extends Filter {
  13.  
  14. /**
  15. *
  16. * @param invoker
  17. * @param invocation
  18. * @return
  19. * @throws RpcException
  20. */
  21. @Override
  22. public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
  23. String traceId = MDC.get("traceId");
  24. if (StringUtils.isBlank(traceId)) {
  25. traceId = this.getUUID() ;
  26. }
  27.  
  28. RpcContext.getContext().setAttachment("trace_id", traceId);
  29.      return invoker.invoke(invocation);
  30. }
  31.  
  32. /**
  33. * 获取UUID
  34. * @return String UUID
  35. */
  36. public String getUUID(){
  37. String uuid = UUID.randomUUID().toString();
  38. //替换-字符
  39. return uuid.replaceAll("-", "");
  40. }
  41.  
  42. }

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

  1. String traceId = RpcContext.getContext().getAttachment("trace_id");

3.使用MDC来设置日志变量 %X{traceId}

  1. MDC.put("traceId", traceId);

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

  1. try{
  2. return invoker.invoke(invocation);
  3. }finally {
  4. MDC.remove("traceId");
  5. }

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

  1. RpcContext.getContext().setAttachment("trace_id", traceId);

6.然后在/src/main/resources/META-INF/dubbo/com.alibaba.dubbo.rpc.Filter (或者 com.apache.dubbo.rpc.Filter ) 文件中配置filter

  1. providerRpcTraceFilter=com.xxx.xxx.filter.ProviderRpcTraceFilter
  2. consumerRpcTraceFilter=com.xxx.xxx.filter.ConsumerRpcTraceFilter

7.如果要打印服务器ip,使用com.alibaba.dubbo.common.utils.NetUtils工具获取ip,然后put到MDC里面

  1. String serverIp = NetUtils.getLocalHost()
    MDC.put("serverId", serverIp);

8.设置logback.xml 的日志输出格式

  1. %d{yyyy-MM-dd HH:mm:ss.SSS} [%X{traceId}] [%X{serverId}] [%X{sessionId}] -%5p ${PID:-} [%15.15t] %-40.40logger{39} : %m%n

9.最后通过Kibana对日志进行收集归总,使用trace_id筛选,快速定位到错误位置。

最终效果如下:

注意:

1. dubbo应用同时担任provider、consumer时,RpcTraceFilter 不能合并成一个类,必须分开。

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

PS:

https://blog.csdn.net/qq_20641565/article/details/78627202

https://blog.csdn.net/qq_20641565/article/details/78628115

https://www.jianshu.com/p/3dca4aeb6edd

https://blog.csdn.net/weixin_39178876/article/details/85088410

https://blog.csdn.net/xiaolyuh123/article/details/80560662

Dubbo 分布式 日志 追踪的更多相关文章

  1. Dubbo分布式日志追踪

    使用dubbo分布式框架进行微服务的开发,一个大系统往往会被拆分成很多不同的子系统,并且子系统还会部署多台机器,当其中一个系统出问题了,查看日志十分麻烦. 所以需要一个固定的流程ID和机器ip地址等来 ...

  2. (Dubbo架构)基于MDC+Filter的跨应用分布式日志追踪解决方案

    在单体应用中,日志追踪通常的解决方案是给日志添加 tranID(追踪ID),生成规则因系统而异,大致效果如下: 查询时只要使用 grep 命令进行追踪id筛选即可查到此次调用链中所有日志,但是在 du ...

  3. 【日志追踪】(微服务应用和单体应用)-logback中的MDC机制

    一.MDC介绍 MDC(Mapped Diagnostic Contexts)映射诊断上下文,该特征是logback提供的一种方便在多线程条件下的记录日志的功能, 某些应用程序采用多线程的方式来处理多 ...

  4. .NET Core 中的日志与分布式链路追踪

    目录 .NET Core 中的日志与分布式链路追踪 .NET Core 中的日志 控制台输出 非侵入式日志 Microsoft.Extensions.Logging ILoggerFactory IL ...

  5. 分布式链路追踪自从用了SkyWalking,睡得真香!

    本篇文章介绍链路追踪的另外一种解决方案Skywalking,文章目录如下: 什么是Skywalking? 上一篇文章介绍了分布式链路追踪的一种方式:Spring Cloud Sleuth+ZipKin ...

  6. 基于zipkin分布式链路追踪系统预研第一篇

    本文为博主原创文章,未经博主允许不得转载. 分布式服务追踪系统起源于Google的论文“Dapper, a Large-Scale Distributed Systems Tracing Infras ...

  7. zipkin分布式链路追踪系统

    基于zipkin分布式链路追踪系统预研第一篇   分布式服务追踪系统起源于Google的论文“Dapper, a Large-Scale Distributed Systems Tracing Inf ...

  8. 循序渐进看Java web日志跟踪(1)-Tomcat 日志追踪与配置

    日志,是软件运行过程中,对各类操作中重要信息的记录. 日志跟踪,不管对于怎么样的项目来说,都是非常重要的一部分,它关系到项目后期的维护和排错,起着举足轻重的作用.项目开发过程中,对日志的记录规则,也将 ...

  9. .NET Core微服务之基于Exceptionless实现分布式日志记录

    Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.Exceptionless极简介绍 Exceptionless 是一个开源的实时的日志收集框架,它可以应用在基于 ASP.NET,AS ...

随机推荐

  1. Ios项目添加Pods

    一.概要 iOS开发时,项目中会引用许多第三方库,CocoaPods(https://github.com/CocoaPods/CocoaPods)可以用来方便的统一管理这些第三方库. 二.安装 由于 ...

  2. unity windowEditor平台下鼠标左键控制摄像机的视角

    工作的原因,今天就只写了unity下的鼠标左键控制摄像机的视角左右上下调节:明天,补齐.[有诸多参考,着实是需要多多加油的] using System.Collections; using Syste ...

  3. Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) E. DNA Evolution 树状数组

    E. DNA Evolution 题目连接: http://codeforces.com/contest/828/problem/E Description Everyone knows that D ...

  4. 【搜索】传感器 @upcexam6023

    时间限制: 1 Sec 内存限制: 128 MB 题目描述 SR最近新买了一款电子桌游 这个玩具内部是M个围成一圈的传感器.每个传感器都有开和关两种工作状态,分别用1和0表示.显然,从不同的位置触发沿 ...

  5. flask之SQLAlchemy

    本篇导航: 介绍 使用 SQLAlchemy-Utils 一. 介绍 SQLAlchemy是一个基于Python实现的ORM框架.该框架建立在 DB API之上,使用关系对象映射进行数据库操作,简言之 ...

  6. 【管用】 使用VMtools实现主机Windows与虚拟机Linux文件共享

    实现windows主机与linux虚拟机文件共享,有很多方法,包括使用samba文件服务器等,本文介绍通过vmware虚拟机软件中的vmtools工具来实现文件共享. 一.环境 1.主机:Window ...

  7. Wordpress添加分类

    网址一般不用中文,别名方便让网址更美观,如: xxx/category/new/

  8. 终端下将 man 命令的结果输出到文件保存

    终端下将 man 命令的结果输出到文件保存 在linux或mac下,当我们使用man命令查看某一个命令的详细帮助说明信息时: 可能终端的显示效果不是那么方便: 那么我们可以将man命令的结果输出到tx ...

  9. 洛谷 P1739 表达式括号匹配

    题目链接https://www.luogu.org/problemnew/show/P1739 题目描述 假设一个表达式有英文字母(小写).运算符(+,—,*,/)和左右小(圆)括号构成,以“@”作为 ...

  10. 阿里云 nginx配置ssl证书实现https访问

    一,环境说明 服务器系统:ubuntu16.04LTS 服务器IP地址:47.89.12.99 域名:bjubi.com 二,域名解析到服务器 在阿里云控制台-产品与服务-云解析DNS-找到需要解析的 ...