爲了理解RootMessageId先簡單介紹一下CAT的數據結構設計。CAT客戶端會將全部消息都封裝爲一個完整的消息樹(MessageTree),消息樹可能包括Transaction、Event、Heartbeat、Metric等類型的消息。具體以下:java
歡迎關注微信公衆號:萬貓學社,每週一分享Java技術乾貨。數據庫
其中,Transaction類型的消息可做爲消息樹節點,而其餘消息只可做爲消息樹的葉子節點,也就是Transaction是一個可嵌套的遞歸結構。好比:apache
消息樹的每一節點都有一個屬性messageId,用來惟一表示節點自己,其構成爲:{domain}-{ip}-{timestamp}-{自增index}。另外還有兩個屬性,分別是parentMessageId, rootMessageId。parentMessageId表示父節點的messageId;rootMessageId則表示整個消息樹的根節點的messageId。這兩個屬性在以後CAT的調用鏈分析與分佈式調用鏈分析中發揮了關鍵做用。性能優化
歡迎關注微信公衆號:萬貓學社,每週一分享Java技術乾貨。微信
根據RootMessageId能夠追蹤某一個請求的整個分佈式調用鏈,結合每一條日誌快速定位耗費性能的癥結,作針對性的性能優化。更加方便地作性能優化,特別是TP9五、TP99等指標。數據結構
遇到偶爾發生的bug,是最讓人頭疼的,只有先從日誌中找線索,可是在海量的日誌中找到出現bug的那一個請求是很困難的。有了上游API提供的RootMessageId,就能夠快速過濾出那次請求的全部日誌, 更快速更方便地定位線上bug。app
歡迎關注微信公衆號:萬貓學社,每週一分享Java技術乾貨。dom
固然是每一句日誌上都記錄RootMessageId了。有的同窗會說,這日誌也記錄的太多了。當發現線上問題沒法定位時,你就會狠日誌太少了。其實記錄日誌不怕多,就怕不全。如今硬盤很便宜了,搞個幾T沒有問題,另外還能夠設置日誌清理策略。分佈式
歡迎關注微信公衆號:萬貓學社,每週一分享Java技術乾貨。工具
前面說了那麼多,終於到了今天的壓軸大戲了。實現記錄到日誌有不少種方式,這裏使用的是MDC(Mapped Diagnostic Contexts)。顧名思義,其目的是爲了便於咱們診斷線上問題而出現的方法工具類,目前咱們常常使用的logback和log4j都是支持的。
歡迎關注微信公衆號:萬貓學社,每週一分享Java技術乾貨。
只須要在每一個請求的入口調用MDC.put方法,把rootMessageId賦值進去就能夠了,是否是很簡單?示例代碼:
//在Filter裏,從header裏獲取上下文信息,包括messageId、parentMessageId、rootMessageId CatContext catContext = new CatContext(); catContext.addProperty(Cat.Context.ROOT, request.getHeader(CatConstants.CAT_HTTP_HEADER_ROOT_MESSAGE_ID)); catContext.addProperty(Cat.Context.PARENT, request.getHeader(CatConstants.CAT_HTTP_HEADER_PARENT_MESSAGE_ID)); catContext.addProperty(Cat.Context.CHILD, request.getHeader(CatConstants.CAT_HTTP_HEADER_CHILD_MESSAGE_ID)); if (catContext.getProperty(Cat.Context.ROOT) == null) { //若是調用鏈的頂端,沒有上下文信息,須要生成上下文信息 Cat.logRemoteCallClient(catContext); } else { Cat.logRemoteCallServer(catContext); } MDC.put("traceId", catContext.getProperty(Cat.Context.ROOT));
若是你還不知道怎麼集成CAT調用鏈,能夠看看以前的《SpringBoot集成CAT調用鏈實例》
而後,在設置日誌輸出格式的配置文件裏增長[%X{traceId}]
。
Logback的xml配置示例:
<?xml version="1.0" encoding="UTF-8" ?> <configuration scan="true"> <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender"> <layout class="ch.qos.logback.classic.PatternLayout"> <pattern>[%d{yyyy-MM-dd HH:mm:ss.SSS}] [%thread] [%X{traceId}] [%-5level] [%-40.36logger{40}:%-4.4line] - %msg%n</pattern> </layout> </appender> <root level="INFO"> <appender-ref ref="CONSOLE" /> </root> </configuration>
log4j的properties配置示例:
log4j.rootCategory=INFO,stdout,info,error log4j.rootLooger=warn,stdout,info,error log4j.appender.stdout=org.apache.log4j.ConsoleAppender log4j.appender.stdout.layout=org.apache.log4j.PatternLayout log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss,SSS} [%-5p] [%thread] [%X{traceId}] method:%l - %m%n
歡迎關注微信公衆號:萬貓學社,每週一分享Java技術乾貨。