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

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

d3f5a10ce7888afc0b7990295a2a0af8.png

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

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

72cfc9735b5719e7e787583512329865.png

串连ID的实现方式

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

bd4b43747d42c5bec9af011d49de9db0.png

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

MDC对外提供的方法

508080c57dcd7a4fc41d6fe7f19c79d2.png

Logback配置

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

884b2216c84d0f025a8ce016801362e8.png

MDC简单应用例子

4cfd1c24a0d9e1b4a28ddf06400d1ee3.png

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

dfd457cfe8068b8851e855b0e3d2fde4.png

MDC与AOP切面的结合

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

c7bcec75836ba8be55338a522d276fa9.png

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

3b799e60c6896067686fa19fb7c28a80.png

管理每个线程的MDC容器

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

举个例子:

8457f854079ee1960bffb25f281d09b8.png

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

解决方案

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

96ce7575608d03e3a312b5e51d5e4758.png

最后

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

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

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/567273.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

java 图类_Java集合类,一张图说清楚!

作者:skywang12345https://www.cnblogs.com/skywa...2019-03-23 10:32:24Java集合是java提供的工具包,包含了常用的数据结构:集合、链表、队列、栈、数组、映射等。Java集合工具包位置是java.util.*,Java集合主要可以划分为4个部分…

python 取整_马克的Python学习笔记#数字,日期和时间

对数值进行调整在Python中对整数和浮点数进行数字计算是很容易的。但是,如果你需要对分数,数组或者日期和时间进行计算,这就会稍微复杂点。对于简单的取整操作,我们可以使用内建的round(value, ndigits)函数就可,举个例…

java 数据类型分为_JAVA中分为基本数据类型及引用数据类型

byte:Java中最小的数据类型,在内存中占8位(bit),即1个字节,取值范围-128~127,默认值0short:短整型,在内存中占16位,即2个字节,取值范围-32768~32717,默认值0i…

各路由协议的协议号_厂房转让协议

厂房转让协议转让方(甲方):________________受让方(乙方):________________甲乙双方本着平等互利的原则,经协商一致就甲方将其权属的工业用地、厂房等转让与乙方及有关事项达成如下协议:一、工业用地及厂房产权基本情况本协议转让的工业用地位…

java容器怎么封装的_docker怎么把容器打包成镜像

1.首先引用 maven docker插件,打开 java应用jar包,点击package按钮;2.新建一个docker文件夹,将导出的jar包放入到此文件夹中;3.新建一个Dockerfile文件,输入以下打包命令FROM frolvlad/alpine-oraclejdk8:s…

python 异常回溯_关于python:在循环中捕获异常回溯,然后在脚本末尾引发错误...

我正在尝试捕获所有异常错误,然后在脚本结尾处使其引发/显示所有回溯...我有一个主脚本,例如调用我的下标:errors open(MISC/ERROR(S).txt, a)try:execfile("SUBSCRIPTS/Test1.py", {})except Exception:## Spread over two calls…

java web开发常见问题_JavaWeb学习笔记(五)--Web开发其他常见问题

一、把web应用打成war包使用JDK自带jar命令,进入到web应用里面,执行命令:jar -cvf 包名.war . # .表示当前目录所有的文件 直接用jar可查看帮助执行完成后生成一个demo.war文件,把这个文件拷贝到Tomcat的webapps下,Tom…

mysql having in_MySQL中无GROUPBY直接HAVING的问题

本文内容遵从CC版权协议, 可以随意转载, 但必须以超链接形式标明文章原始出处和作者信息及版权声明网址: http://www.penglixun.com/tech/database/having_without_groupby_in_mysql.html 今天有同学给我反应,有一张表,id是主键,这样的写法可…

python求线段长度_python微元法计算函数曲线长度的方法

计算曲线长度,根据线积分公式:,令积分函数f(x,y,z) 为1,即计算曲线的长度,将其微元化:其中根据此时便可在python编程实现,给出4个例子,代码中已有详细注释,不再赘述计算曲…

java if 顺序 括号_03-03 java 顺序语句结构,选择结构if语句

/*if语句的格式3:if(比较表达式1) {语句体1;}else if(比较表达式2) {语句体2;}else if(比较表达式3) {语句体3;}...else {语句体n1;}执行流程:首先计算比较表达式1看其返回值是true还是false,如果是true,就执行语句体1&#xff0c…

java 项目部署_java项目部署

本文章只为帮助大家学习项目的发布,为基础篇,在此给大家示范在window环境下的项目部署及运维。以下版本为讲解示例,可自行改至匹配版本。服务器:window service2008 R2 Standard(提前准备好服务器,可以在服务器商家租服…

电气专业学python吗_985大学毕业起薪最高的五个专业,计算机、金融、电气上榜!...

本科毕业生起薪是指本科毕业生第一份工作能够获得的薪资水平,大学毕业生的起薪一般会因为学校、专业、地区的不同而有所差异。一般来说,985大学毕业生的起薪要比普通大学毕业生的起薪高一点,那么,985大学中,哪些专业的…

python核心教程_python核心教程--第四章

第四章讲的是python对象。4.1 python对象所有的python对象都拥有三个特性:身份,类型和值身份:每一个对象都有一个唯一的身份标识自己,任何对象的身份可以使用内建函数id()来得到。这个值可以被认为是该对象的内存地址。类型&#…

uwsgi怎么通过浏览器访问某个脚本_4个Shell小技巧帮你提高机器学习效率:写好脚本,事半功倍...

晓查 发自 凹非寺 量子位 报道 | 公众号 QbitAI在机器学习的实践过程中,用好Shell能帮你很多节省时间。最近,有位来自ETHZ的学生分享了一些Shell小技巧。对程序员来说,这些技巧更重要的是让你的思维从琐碎小事中解脱出来,大大提高…

java file 字符串_Java读取一个文本文件拼接成一个字符串(readFileToString)

import java.io.BufferedReader;import java.io.File;import java.io.FileInputStream;import java.io.IOException;import java.io.InputStreamReader;import org.junit.Test;public class Demo {// 使用示例Testpublic void testName1() throws Exception {String filePath …

pythonselenium上传图片视频_如何用selenium、python上传文件(图片)

我添加了一个答案,任何人想使用处理恼人的msofiledialogs。这是对saravanan提出的解决方案的改进,但对Python来说更加充实。我也遇到过类似的问题,我正在为一家公司做脚本。我试图为一家公司的客户上传文件,但由于他们的网站工作方…

java中的.运算符_java中的各种运算符

1、算术运算符;算术运算符也就是我们小学所学过的: - */;还有取模运算符:%;取模运算符也就是求余的运算;运算形式:操作数 操作数;操作数 - 操作数;操作数 *操作数&#…

python curl 获取返回值_python获取系统命令的返回值 | curl in python

项目背景:通过curl 命令 从服务器获取数组,tids,然后导入到Mysql 表中。自己想的方案:shell命令不熟悉,另外python中的数据库等接口都已封装,所以想使用Python来做,利用Python调用shell命令。cu…

java 绑定属性_Java的动态绑定

看这段代码Father father new Son();父类引用指向子类对象,这是java的多态特性,有多态引到动态绑定,如何引入呢,看这个代码:classFather{privateString nameString;public voidspeak() {System.out.println(this.getC…

中软python编码规范考试试题_卓越分享 | 如何写出一手漂亮的Python代码?

该楼层疑似违规已被系统折叠 隐藏此楼查看此楼Python语言这么火,有很多同学是从其他语言转行过来的(比如c,java语言),多多少少写代码的时候也会受其他语言的影响!而对于刚开始学编程的小白同学来说,解决问题的思路有的…