Dubbo分布式日志追踪
使用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

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)
Dubbo分布式日志追踪的更多相关文章
- Dubbo 分布式 日志 追踪
使用dubbo分布式框架进行微服务的开发,一个大系统往往会被拆分成很多不同的子系统,并且子系统还会部署多台机器,当其中一个系统出问题了,查看日志十分麻烦. 所以需要一个固定的流程ID和机器ip地址等来 ...
- (Dubbo架构)基于MDC+Filter的跨应用分布式日志追踪解决方案
在单体应用中,日志追踪通常的解决方案是给日志添加 tranID(追踪ID),生成规则因系统而异,大致效果如下: 查询时只要使用 grep 命令进行追踪id筛选即可查到此次调用链中所有日志,但是在 du ...
- 【日志追踪】(微服务应用和单体应用)-logback中的MDC机制
一.MDC介绍 MDC(Mapped Diagnostic Contexts)映射诊断上下文,该特征是logback提供的一种方便在多线程条件下的记录日志的功能, 某些应用程序采用多线程的方式来处理多 ...
- .NET Core 中的日志与分布式链路追踪
目录 .NET Core 中的日志与分布式链路追踪 .NET Core 中的日志 控制台输出 非侵入式日志 Microsoft.Extensions.Logging ILoggerFactory IL ...
- 分布式链路追踪自从用了SkyWalking,睡得真香!
本篇文章介绍链路追踪的另外一种解决方案Skywalking,文章目录如下: 什么是Skywalking? 上一篇文章介绍了分布式链路追踪的一种方式:Spring Cloud Sleuth+ZipKin ...
- 基于zipkin分布式链路追踪系统预研第一篇
本文为博主原创文章,未经博主允许不得转载. 分布式服务追踪系统起源于Google的论文“Dapper, a Large-Scale Distributed Systems Tracing Infras ...
- zipkin分布式链路追踪系统
基于zipkin分布式链路追踪系统预研第一篇 分布式服务追踪系统起源于Google的论文“Dapper, a Large-Scale Distributed Systems Tracing Inf ...
- 循序渐进看Java web日志跟踪(1)-Tomcat 日志追踪与配置
日志,是软件运行过程中,对各类操作中重要信息的记录. 日志跟踪,不管对于怎么样的项目来说,都是非常重要的一部分,它关系到项目后期的维护和排错,起着举足轻重的作用.项目开发过程中,对日志的记录规则,也将 ...
- .NET Core微服务之基于Exceptionless实现分布式日志记录
Tip: 此篇已加入.NET Core微服务基础系列文章索引 一.Exceptionless极简介绍 Exceptionless 是一个开源的实时的日志收集框架,它可以应用在基于 ASP.NET,AS ...
随机推荐
- 前端JS AES加密 后端PHP AES加解密
<!DOCTYPEhtml> <html> <head> <title>aes demo</title> </head> < ...
- 在PowerShell中操作SharePoint对象
1. 用PowerShell创建一个SharePoint内容对象创建一个自定义列表:$SPSite = New-Object Microsoft.SharePoint.SPSite("htt ...
- Python学习过程(二)
条件判断和循环 条件判断 age = 20 if age >= 18: print 'your age is',age print 'adult' elif age >=6 : print ...
- SP7258 SUBLEX - Lexicographical Substring Search
\(\color{#0066ff}{ 题目描述 }\) 给定一个字符串,求排名第k小的串 \(\color{#0066ff}{输入格式}\) 第一行给定主串(len<=90000) 第二行给定询 ...
- luogu2658 GCD(莫比乌斯反演/欧拉函数)
link 给定整数N,求1<=x,y<=N且Gcd(x,y)为素数的数对(x,y)有多少对. 1<=N<=10^7 (1)莫比乌斯反演法 发现就是YY的GCD,左转YY的GCD ...
- Leetcode 520. Detect Capital 发现大写词 (字符串)
Leetcode 520. Detect Capital 发现大写词 (字符串) 题目描述 已知一个单词,你需要给出它是否为"大写词" 我们定义的"大写词"有下 ...
- Vue中添加过渡效果
最近在学习Vue这个框架,发现新的版本中,官网的文档里面说的过渡效果,如果直接粘贴官方的例子中的代码,发现并没有过渡的效果,经过反复测试之后终于知道怎么搞了,把测试的过程总结一下,以便以后回顾. 贴上 ...
- C++基础学习5:强制类型转换
在C++语言中新增了四个关键字static_cast.const_cast.reinterpret_cast和dynamic_cast.这四个关键字都是用于强制类型转换的.我们逐一来介绍这四个关键字. ...
- __weak 和 __strong 还有Autorelease的用法
使用容器的block版本的枚举器时,内部会自动添加一个AutoreleasePool: Autorelease对象是在当前的runloop迭代结束时释放的,而它能够释放的原因是系统在每个runloop ...
- css3文本域焦点烟花效果
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...