Dubbo實(shí)現(xiàn)分布式日志鏈路追蹤
技術(shù)場(chǎng)景
在日常的開發(fā)、測(cè)試或運(yùn)維的過(guò)程中,經(jīng)常存在這樣的場(chǎng)景,開發(fā)人員在代碼中使用日志工具(log4j、slf4j)記錄日志,比如請(qǐng)求ID、IP等,方便在線上快速、精準(zhǔn)的定位問(wèn)題,通過(guò)完整的日志鏈路清晰的進(jìn)行信息定位。
一般的項(xiàng)目都是分層的、分布式的,在眾多的日志信息中,如何區(qū)分哪些日志信息是同一請(qǐng)求發(fā)出來(lái)的,詳細(xì)的實(shí)現(xiàn)如下。
技術(shù)框架
項(xiàng)目框架:Spring boot
分布式協(xié)調(diào):Zookeeper、Dubbo
日志工具:Sf4j
構(gòu)建工具:Maven
開發(fā)工具:IDEA
項(xiàng)目框架

mdc-dubbo-api:接口服務(wù)
mdc-dubbo-provider:服務(wù)端服務(wù)
mdc-dubbo-consumer:消費(fèi)端服務(wù)
項(xiàng)目配置
mdc-dubbo-api
提供一個(gè)接口
public interface OrderService {
String getOrder(String orderid);
}
mdc-dubbo-consumer
在服務(wù)端,在Controller層使用MDC工具類放入一個(gè)TRACE_LOG_ID信息,在此請(qǐng)求的service層、mdc-dubbo-provider中使用該信息。

項(xiàng)目分為Controller、Service、Filter等各層:
Controller層:存放TRACE_LOG_ID, 打印
@GetMapping("get/{id}")
public String get(@PathVariable("id") String id){
String uuid = UUID.randomUUID().toString().replaceAll("-", "");
MDC.put(Constants.TRACE_LOG_ID, uuid);
LOGGER.info("controller->param:{}", id);
return consumerService.getName(id);
}
Service層:打印TRACE_LOG_ID
@Override
public String getName(String id) {
LOGGER.info("consumer->service->param:{}", id);
return orderService.getOrder(id);
}
Filter:
public class TraceFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
//從MDC中獲取
String logId = MDC.get(Constants.TRACE_LOG_ID);
Map<String, String> attachments = invocation.getAttachments();
attachments.put(Constants.TRACE_LOG_ID, logId);
return invoker.invoke(invocation);
}
需要過(guò)濾器配置在resources->MATE-INF->dobbo文件夾下
![過(guò)濾器配置https://img-blog.csdnimg.cn/20181219100406136.png)
traceFilter=com.bestpay.provider.filter.TraceFilter
此處注意 此處使用到了Dubbo中spi機(jī)制,文件名必須是com.alibaba.dubbo.rpc.Filter
dubbo配置文件
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://code.alibabatech.com/schema/dubbo
http://code.alibabatech.com/schema/dubbo/dubbo.xsd">
<!--過(guò)濾器配置-->
<!-- <dubbo:provider filter="traceFilter" />-->
<!-- 應(yīng)用名-->
<dubbo:application name="dmc-dubbo-provider"/>
<!--zookeeper注冊(cè)中心-->
<dubbo:registry address="zookeeper://127.0.0.1:2181"/>
<dubbo:protocol name="dubbo" port="20880"/>
<!--服務(wù)注冊(cè)-->
<dubbo:service interface="com.bestpay.service.OrderService" ref="orderService" timeout="10000" **filter="traceFilter"**/>
<bean id="orderService" class="com.bestpay.provider.service.OrderServiceImpl" />
</beans>
其中filter="traceFilter是引用dobbo目錄下配置中的key
logback配置
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>[%date{yyyy-MM-dd HH:mm:ss}] [%-5level] %logger %line --%mdc{client} [%X{TRACE_LOG_ID}] %msg%n</pattern>
<!-- 控制臺(tái)也要使用UTF-8,不要使用GBK,否則會(huì)中文亂碼 -->
<charset>UTF-8</charset>
</encoder>
</appender>
TRACE_LOG_ID對(duì)應(yīng)放入MDC中的key
mdc-dubbo-provider
配置和## mdc-dubbo-consumer類似,其中在Filter上稍微有些差別
public class TraceFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
String logId = invocation.getAttachment(Constants.TRACE_LOG_ID);
MDC.put(Constants.TRACE_LOG_ID, logId);
return invoker.invoke(invocation);
}
}
項(xiàng)目運(yùn)行
mdc-dubbo-consumer日志:
[2018-12-19 10:16:56] [INFO ] com.bestpay.comsumer.controller.ConsumerController 33 – [d88ecba6581c47b1b3ade78d2821d13a] controller->param:223
[2018-12-19 10:16:56] [INFO ] com.bestpay.comsumer.service.impl.ComsumerServiceImpl 20 – [d88ecba6581c47b1b3ade78d2821d13a] consumer->service->param:223mdc-dubbo-provider日志:
[2018-12-19 10:16:56] [INFO ] com.bestpay.provider.service.OrderServiceImpl 13 – [d88ecba6581c47b1b3ade78d2821d13a] provider->service->param:223
以上,完成了dubbo分布式服務(wù)之間日志的完整鏈路。為個(gè)人經(jīng)驗(yàn),希望能給大家一個(gè)參考,也希望大家多多支持腳本之家。
相關(guān)文章
IDEA中springboot提示java:找不到符號(hào)符號(hào):變量log問(wèn)題
這篇文章主要介紹了IDEA中springboot提示java:找不到符號(hào)符號(hào):變量log問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-04-04
spring boot使用i18n時(shí)properties文件中文亂碼問(wèn)題的解決方法
一篇文章帶你了解一些Java反射的學(xué)習(xí)記錄
Java實(shí)現(xiàn)的計(jì)算最大下標(biāo)距離算法示例
簡(jiǎn)述JAVA中堆內(nèi)存與棧內(nèi)存的區(qū)別

