导读:在实际开发中,打印日志是十分重要的。在生产环境中,如果日志打得好可以快速地排查问题,而在分布式的场景下,一个请求会跨越多个节点,既一个业务可能需要多个节点协调配合处理。那么日志将会分散,而为了更好的查看日志,我们需要将它们串联起来,这样便会使排查问题变得更佳轻松。

串联ID在分布式日志打印的好处

举例一个简单分布式场景下使用串联日志的例子。场景如下:一笔支付请求从产品系统发起,期间经历了核心系统和网关系统最后调用银行系统实现资金划转,并逐步响应结果直到回到产品系统。这里暂且把整个支付流程看作是同步的,当这笔交易在生产环境中因其中某一环境出现异常时,我们需查看日志进行排查,而这笔交易因为流经多个系统,所以日志是分散的。这时候如果有一个唯一标识且能把所有日志串联起来那么将会方便和提高问题排查的效率。

串连ID的实现方式

串联的核心要点是把ID做为一个请求必传参数。常见如采用手动打印日志,既在各个接口服务内多处加上logger打印,打印内容里加上串联ID,如:

但是,还有另一种更简便的打印方式,既是MDC ( Mapped Diagnostic Contexts ) + AOP切面结合。MDC它是一个线程安全的存放诊断日志的容器。在处理请求前将请求的唯一标示放到MDC容器中,这个唯一标示会随着日志一起输出,以此来区分该条日志是属于那个请求的。并在请求处理完成之后清除MDC容器。

MDC对外提供的方法

Logback配置

使用Logback的MDC机制,需要在logback.xml日志模板中进行一些设置,在logback.xml中,通过使用 %X{ }来占位,替换到对应的MDC中key的值。MDC容器的key可以多次赋值,每一次赋值会覆盖上一次的值。

MDC简单应用例子

往MDC容器中put入键值对,在日志打印时,日志会按照我们预先在logback.xml中的格式输出,而其中占位符会替换上MDC中对应key的value值。打印结果如下:

MDC与AOP切面的结合

如编写一个切面,被调用的服务在执行操作前,切面会将关键信息输出日志并同时将串联ID put到容器中,使其能在接下来同一线程内输出的日志中都包含该串联ID信息,在将日志串联起来的同时也方便了日志的打印。

除了自定义切面外,Logback也提供了一个过滤器MDCInsertingServletFilter,感兴趣的朋友可以去详细了解下。

管理每个线程的MDC容器

这里要特别要注意一点的是在主线程上,新起一个子线程,并由 java.util.concurrent.Executors来执行它时,在早期的版本中子线程可以直接自动继承父线程的MDC容器中的内容,因为MDC在早期版本中使用的是InheritableThreadLocal来作为底层实现。但是由于性能问题被取消了,最后还是使用的是ThreadLocal来作为底层实现。这样子线程就不能直接继承父线程的MDC容器。

举个例子:

例如:支付操作为异步时,网关接收了核心的支付请求后会新开一个线程去处理支付请求,并响应回核心受理成功(注意:这里受理代表接收到支付的请求,而不代表处理成功)。那这样做就会导致新的子线程MDC并没有继承父线程中的东西,导致响应结果时缺失串联ID信息,不能与支付请求关联起来。

解决方案

根据以上问题,Logback官方建议父线程新建子线程之前调用MDC.getCopyOfContextMap()方法将MDC内容取出来传给子线程,子线程在执行操作前先调用MDC.setContextMap()方法将父线程的MDC内容设置到子线程。

最后

以上就是分布式场景下一种较为不错的日志打印方式,通过结合AOP切面与Logback的MDC机制将多个系统间有关联的日志串联起来,有助于问题的排查及信息的查看。如果有其他不错的日志打印方式也欢迎提出,共同讨论学习。

感谢您的阅读,如果喜欢本文欢迎关注和转发,本头条号将坚持原创,持续分享IT技术知识。对于文章内容有其他想法或意见建议等,欢迎提出共同讨论共同进步

切面是异步还是同步操作‘_分布式中采用Logback的MDC机制与AOP切面结合串联日志...相关推荐

  1. 切面是异步还是同步操作‘_【 .NET Core 3.0 】框架之十 || AOP 切面思想

    本文有配套视频: https://www.bilibili.com/video/av58096866/?p=6 前言 上回<[ .NET Core3.0 ]框架之九 || 依赖注入IoC学习 + ...

  2. 切面是异步还是同步操作‘_细说JS异步发展历程

    知其然知其所以然,首先了解三个概念: 1.什么是同步? 所谓同步,就是在发出一个"调用"时,在没有得到结果之前,该"调用"就不返回.但是一旦调用返回,就得到返回 ...

  3. 切面是异步还是同步操作‘_Autofac的AOP面向切面编程研究

    什么是AOP: 我的理解是 把系统性的编程工作封装起来 =>我给这个取个名字叫 "Aspect",然后通过AOP技术把它切进我们的业务逻辑代码 => "业务& ...

  4. mysql集群怎么实现状态机_分布式中的状态机

    全局锁 在系统访问单个资源时或多或少都会要使用到锁,如Java的Lock等,但多个系统访问资源,或在集群中各个实例需要访问资源时,就需要建立全局的锁,这里讲三种全局锁的方法. 数据库 利用ACID 使 ...

  5. javascript等待异步线程完成_作为前端你了解JavaScript运行机制吗?

    作为前端工程师,大家都知道js是前端一开始就要学会的知识点,js的代码你会写了,那js的运行机制你了解吗?只有了解了js的运行机制,才能在工作中如鱼得水,今天就跟随珠峰的老师一起来了解下js的运行机制 ...

  6. for循环延时_前端中的事件循环eventloop机制

    我们知道 js 是单线程执行的,那么异步的代码 js 是怎么处理的呢?例如下面的代码是如何进行输出的: console.log(1);setTimeout(function() { console.l ...

  7. springboot异步和切面_spring中的切面和异步执行

    1.首先理解异步和多线程的概念,怎么实现接口的异步调用呢?多线程,这是很多人第一眼想到的关键词,没错,多线程就是一种实现异步调用的方式! 2.下面介绍怎么实现异步调用方式 3.首先如果你的项目是spr ...

  8. Springboot AOP切面

    文章目录 SpringBoot Aop 切面(Aop) 一.什么是切面 二.切面的用途 三.AOP切面常用注解 四.详细内容 1.切面(Aspect) 2.连接点(Joinpoint) 3.通知(Ad ...

  9. stm32怎么调用for循环内部的变量_循环中的异步amp;amp;循环中的闭包

    在这之前先要了解一下 for循环中let 和var的区别 var 是函数级作用域或者全局作用域,let是块级作用域 看一个例子     function foo() {       for (var  ...

最新文章

  1. 脑电分析系列[MNE-Python-1]| MNE-Python详细安装与使用(更新)
  2. python联盟是什么意思_Python 与 英雄联盟(1)
  3. scrapy爬虫代理——利用crawlera神器,无需再寻找代理IP
  4. python 距离矩阵_创建距离矩阵?
  5. 命令终端(CMD)自动补全功能 — Tab Complete 功能
  6. 死锁产生的原因及条件和手写死锁
  7. unittest-常见问题解决方案记录
  8. epoll和poll的C++11多线程练习
  9. CRC源码生成工具,可生成Verilog和VHDL
  10. Java在websocket获取Httpsession及bean无法注入问题
  11. TWS耳机供应链,看看背后都有谁?
  12. html如何制作水滴效果图,html+css实现充电水滴融合特效代码
  13. c4d怎么导入fbx_c4d怎么导入模型?品索教你Maya模型文件如何导入到C4d
  14. android高德地图 画质,高德导航地图端口和分辨率修改
  15. 飞鹅云打印机api接口asp版,asp源码对接飞鹅云小票打印机
  16. self的用法与意义(一)
  17. 500G技术资源分享
  18. java 1.7.0 51下载 64_JD7K_jd7k-7u51-windows-x64.exe V7.0u51 64位 官方版
  19. 好程序员web前端培训分享做H5页面需要学什么
  20. 随机数生成(一):均匀分布

热门文章

  1. SpringMVC注解@RequestParam全面解析____ 注解@RequestParam如何使用加与不加的区别
  2. angularjs input标签用一个日期插件后数据不能双向绑定了_微信如何定时发朋友圈?(最方便最好用的办法!)...
  3. kido机器人用流量吗_国脉电信200元天网卡,交1700流量无线用,拉人加入还会有不错的收益,你信吗?反正我是不信!...
  4. mysql批量查询版本号最大的_mysql子查询批量找id最大的
  5. matlab安装好 启动总是闪退_在Ubuntu16.04下安装MATLAB2017b
  6. linux脚本怎么把文件地址变成动态地址,Linux脚本程序自动修改网卡配置文件中的MAC地址...
  7. mysql 删除not null_从MySQL的列中删除NOT NULL限制?
  8. java tostring的用处_JAVA的tostring()方法的作用是什么呢?
  9. 利用next_permutation解答全排列问题
  10. centos 等保三级_等保测评三级整改-身份鉴别