Dubbo實(shí)現(xiàn)分布式日志鏈路追蹤
技術(shù)場(chǎng)景
在日常的開(kāi)發(fā)、測(cè)試或運(yùn)維的過(guò)程中,經(jīng)常存在這樣的場(chǎng)景,開(kāi)發(fā)人員在代碼中使用日志工具(log4j、slf4j)記錄日志,比如請(qǐng)求ID、IP等,方便在線(xiàn)上快速、精準(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
開(kāi)發(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工具類(lèi)放入一個(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類(lèi)似,其中在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è)參考,也希望大家多多支持腳本之家。
- dubbo如何實(shí)現(xiàn)consumer從多個(gè)group中調(diào)用指定group的provider
- java開(kāi)發(fā)Dubbo注解Adaptive實(shí)現(xiàn)原理
- Dubbo異步調(diào)用的實(shí)現(xiàn)介紹
- springBoot+dubbo+zookeeper實(shí)現(xiàn)分布式開(kāi)發(fā)應(yīng)用的項(xiàng)目實(shí)踐
- nodejs連接dubbo服務(wù)的java工程實(shí)現(xiàn)示例
- 實(shí)現(xiàn)一個(gè)簡(jiǎn)單Dubbo完整過(guò)程詳解
相關(guān)文章
java實(shí)現(xiàn)protocol傳輸?shù)目蛻?hù)端和服務(wù)端的示例代碼
本文主要介紹了java實(shí)現(xiàn)protocol傳輸?shù)目蛻?hù)端和服務(wù)端的示例代碼,基于TCP協(xié)議的客戶(hù)端和服務(wù)端,包括了基本的連接、消息傳遞和關(guān)閉連接的操作,感興趣的可以了解一下2024-07-07java中Integer包裝類(lèi)裝箱的一個(gè)細(xì)節(jié)詳解
Java中的Integer是int的包裝類(lèi)型,下面這篇文章主要給大家介紹了關(guān)于java中Integer包裝類(lèi)裝箱的一個(gè)細(xì)節(jié)的相關(guān)資料,文中介紹的這個(gè)細(xì)節(jié)挺重要的,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起看看吧2018-07-07maven創(chuàng)建spark項(xiàng)目的pom.xml文件配置demo
這篇文章主要為大家介紹了maven創(chuàng)建spark項(xiàng)目的pom.xml文件配置demo,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05Plugin ‘org.springframework.boot:spring-boot-maven-plug
這篇文章給大家介紹了Plugin ‘org.springframework.boot:spring-boot-maven-plugin:‘ not found的解決方案,親測(cè)可用,文中給出了兩種解決方法,需要的朋友可以參考下2024-01-01解決IDEA占用C盤(pán)空間過(guò)大的問(wèn)題
這篇文章主要介紹了解決IDEA占用C盤(pán)空間過(guò)大的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-02-02深入理解 Java 中的 Switch 語(yǔ)句示例詳解
在Java編程中,switch語(yǔ)句通過(guò)表達(dá)式值來(lái)執(zhí)行不同代碼塊,本文介紹switch語(yǔ)法、案例、注意事項(xiàng),以及與if語(yǔ)句的對(duì)比,包括基本語(yǔ)法、關(guān)鍵字、表達(dá)式、case常量、break和default的使用,以及如何根據(jù)輸入的字符輸出星期、大小寫(xiě)轉(zhuǎn)換、成績(jī)判斷和季節(jié)判斷等實(shí)際應(yīng)用場(chǎng)景2024-10-10淺談spring boot使用thymeleaf版本的問(wèn)題
這篇文章主要介紹了spring boot使用thymeleaf版本的問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-08-08