<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          自從項(xiàng)目上了這款輕量級(jí)日志追蹤神器,睡覺(jué)真香!

          共 6091字,需瀏覽 13分鐘

           ·

          2023-01-12 20:47

          背景

          隨著微服務(wù)盛行,很多公司都把系統(tǒng)按照業(yè)務(wù)邊界拆成了很多微服務(wù),在排錯(cuò)查日志的時(shí)候,因?yàn)闃I(yè)務(wù)鏈路貫穿著很多微服務(wù)節(jié)點(diǎn),導(dǎo)致定位某個(gè)請(qǐng)求的日志以及上下游業(yè)務(wù)的日志會(huì)變得有些困難。

          這時(shí)候可能有的小伙伴就會(huì)想到使用SkyWalking,Pinpoint等分布式追蹤系統(tǒng)來(lái)解決,并且這些系統(tǒng)通常都是無(wú)侵入性的,同時(shí)也會(huì)提供相對(duì)友好的管理界面來(lái)進(jìn)行鏈路Span的查詢,但是搭建分布式追蹤系統(tǒng)還是需要一定的成本的,所以本文要說(shuō)的并不是這些分布式追蹤系統(tǒng),而是一款簡(jiǎn)單、易用、幾乎零侵入、適合中小型公司使用的日志追蹤框架TLog。

          TLog簡(jiǎn)介

          TLog提供了一種最簡(jiǎn)單的方式來(lái)解決日志追蹤問(wèn)題,TLog會(huì)自動(dòng)的對(duì)你的日志進(jìn)行打標(biāo)簽,幫你自動(dòng)生成traceId貫穿你微服務(wù)的一整條鏈路,在排查日志的時(shí)候,可以根據(jù)traceId來(lái)快速定位請(qǐng)求處理的鏈路。

          TLog不收集日志,只在對(duì)你原來(lái)打印的日志上增強(qiáng),將請(qǐng)求鏈路信息traceId綁定到你打印的日志上。當(dāng)出現(xiàn)微服務(wù)中那么多節(jié)點(diǎn)的情況,官方推薦使用TLog+日志收集方案來(lái)解決。當(dāng)然分布式追蹤系統(tǒng)其實(shí)是鏈路追蹤一個(gè)最終的解決方案,如果項(xiàng)目中已經(jīng)上了分布式追蹤系統(tǒng),那TLog并不適用。

          如下圖,是ELK配合TLog,快速定位請(qǐng)求處理的鏈路的示例。

          TLog接入

          1、接入步驟

          1.1、引入依賴
          <dependency>
              <groupId>com.yomahub</groupId>
              <artifactId>tlog-all-spring-boot-starter</artifactId>
              <version>1.5.0</version>
          </dependency>
          1.2、替換logback配置項(xiàng)

          到這其實(shí)就已經(jīng)完成了配置。

          1.3、測(cè)試

          這里是通過(guò)slf4j的LoggerFactory獲取Logger對(duì)象,因?yàn)閘ogback適配了slf4j,最終會(huì)通過(guò)logback來(lái)輸出日志。

          從這可以看出,11794076298070144 就是本次日志輸出的時(shí)候生成的一個(gè)請(qǐng)求的traceId,在排查日志的時(shí)候就可以通過(guò)這個(gè)traceId去搜索出整個(gè)請(qǐng)求的鏈路日志。

          2、TLog接入方式

          TLog總共提供了三種方式接入項(xiàng)目

          • Javaagent接入方式
          • 字節(jié)碼注入方式
          • 日志框架適配器方式

          上面案例的接入方式其實(shí)是屬于日志框架適配器方式,并且是對(duì)于Logback框架的適配。TLog除了適配了Logback框架,還適配了Log4j框架和Log4j2框架,項(xiàng)目中可自行選擇。

          Javaagent接入方式和字節(jié)碼注入方式相比與日志框架適配器方式對(duì)代碼的入侵性更小,但是這兩種方式僅僅只支持SpringBoot項(xiàng)目,并且相較于日志框架適配器的方式,MDC和異步日志功能并不支持,所以要想完整體驗(yàn)TLog的功能,還是建議選擇日志框架適配器方式,日志框架適配器方式其實(shí)接入也很快,其實(shí)也就是修改一下配置文件的事。

          項(xiàng)目環(huán)境兼容對(duì)比
          特性支持對(duì)比

          TLog的基本原理

          1、日志標(biāo)簽

          前面在介紹TLog的時(shí)候,提到TLog會(huì)自動(dòng)的對(duì)你的日志進(jìn)行打標(biāo)簽,這個(gè)標(biāo)簽就是日志標(biāo)簽,一個(gè)日志標(biāo)簽最多可以包含如下信息:

          • preApp:接口調(diào)用方服務(wù)名
          • preHost:接口調(diào)用方Host
          • preIp:接口調(diào)用方ip
          • currIp:當(dāng)前服務(wù)ip
          • traceId:鏈路id,調(diào)用方如果傳遞就是傳遞的值,不傳遞就會(huì)重新生成
          • spanId:鏈路spanId

          默認(rèn)是按照如下labelPattern進(jìn)行數(shù)據(jù)拼接生成日志標(biāo)簽,所以默認(rèn)只打出spanId和traceId。

          這也就是上面為什么示例中會(huì)輸出 <0><11794076298070144> 這種格式的原因,前面的0其實(shí)就是spanId。

          如果你想改變?nèi)罩緲?biāo)簽輸出其它信息或者輸出的順序,只需要在SpringBoot配置文件中配置日志標(biāo)簽的生成樣式就行。

          tlog.pattern=[$preApp][$preIp][$spanId][$traceId]

          2、TLogContext

          TLogContext是TLog是一個(gè)核心的組件,這個(gè)組件內(nèi)部是使用了TransmittableThreadLocal來(lái)傳遞traceId、preApp等信息。

          當(dāng)有一個(gè)請(qǐng)求過(guò)來(lái)的時(shí)候,會(huì)從解析出traceId、preApp等信息,然后設(shè)置到TransmittableThreadLocal中,之后就可以在整個(gè)調(diào)用鏈路中從TLogContext中獲取到traceId等信息。

          3、TLogRPCHandler

          這個(gè)組件是用來(lái)處理調(diào)用方傳遞的traceId、preApp等信息,設(shè)置到TLogContext和MDC中,同時(shí)根據(jù)日志標(biāo)簽的格式生成日志標(biāo)簽。

          第三方框架的適配

          在實(shí)際項(xiàng)目中,一個(gè)請(qǐng)求處理過(guò)程可能會(huì)出現(xiàn)以下情況

          • 異步線程處理
          • 跨服務(wù)調(diào)用
          • MQ調(diào)用

          那么對(duì)于這些情況來(lái)說(shuō),traceId應(yīng)該需要在異步線程、跨服務(wù)、MQ等中傳遞,以便更好地排查一個(gè)請(qǐng)求的處理鏈路。

          而TLog對(duì)于以上可能出現(xiàn)的情況都做了大量的適配,保證traceId能夠在異步線程、微服務(wù)間、MQ等中能夠正確傳遞。

          1、異步線程

          1.1 一般異步線程

          所謂的一般異步線程就是指直接通過(guò)new Thread的方法來(lái)創(chuàng)建異步線程,然后來(lái)執(zhí)行,這種方式TLog是天然支持?jǐn)y帶traceId的,如圖。

          執(zhí)行結(jié)果

          從這可以看出這種異步方式的確成功傳遞了traceId。

          1.2 線程池

          對(duì)于線程池來(lái)說(shuō),其實(shí)默認(rèn)也是支持傳遞traceId,但是由于線程池中的線程是可以復(fù)用了,為了保證線程間的數(shù)據(jù)互不干擾,需要使用TLogInheritableTask將提交的任務(wù)進(jìn)行包裝。

          ThreadPoolExecutor pool =
                  new ThreadPoolExecutor(121, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10));
          pool.execute(new TLogInheritableTask() {
              @Override
              public void runTask() {
                logger.info("異步執(zhí)行");
              }
          });

          上述代碼的寫法會(huì)有點(diǎn)耦合,每次提交任務(wù)都需要?jiǎng)?chuàng)建一個(gè)TLogInheritableTask,比較麻煩,可以按如下寫法進(jìn)行簡(jiǎn)化。

          TLogThreadPoolExecutor

          自己寫個(gè)TLogThreadPoolExecutor繼承ThreadPoolExecutor,重寫execute方法(submit最終也會(huì)調(diào)用execute方法執(zhí)行),然后將提交的任務(wù)統(tǒng)一包裝成TLogInheritableTask,這樣需要使用線程池的地方直接創(chuàng)建TLogThreadPoolExecutor就可以了,就不需要在提交任務(wù)的時(shí)候創(chuàng)建TLogInheritableTask了。

          ThreadPoolExecutor pool =
                  new TLogThreadPoolExecutor(121, TimeUnit.SECONDS, new LinkedBlockingQueue<>(10));
          pool.execute(() -> logger.info("異步執(zhí)行"));

          2、對(duì)RPC框架的支持

          除了對(duì)異步線程的支持,TLog也支持常見(jiàn)的Dubbo,Dubbox,OpenFeign三大RPC框架,在SpringBoot項(xiàng)目中不需要任何配置,只需要引入依賴就可以實(shí)現(xiàn)traceId在服務(wù)之間的傳遞

          2.1 對(duì)Dubbo和Dubbox的支持

          對(duì)于Dubbo和Dubbox的支持是基于Dubbo的Filter擴(kuò)展點(diǎn)來(lái)的

          TLog通過(guò)SPI機(jī)制擴(kuò)展Filter,在消費(fèi)者發(fā)送請(qǐng)求前從TLogContext獲取到traceId,然后將traceId和其它調(diào)用者數(shù)據(jù)設(shè)置請(qǐng)求數(shù)據(jù)中,服務(wù)提供者在處理請(qǐng)求的時(shí)候,也會(huì)經(jīng)過(guò)Filter,從請(qǐng)求中獲取到traceId等信息,然后設(shè)置到TLogContext中,從而實(shí)現(xiàn)了traceId在dubbo的消費(fèi)者和提供者之間的傳遞。

          2.2 對(duì)OpenFeign的支持

          對(duì)于OpenFeign的支持其實(shí)也是通過(guò)Feign提供的擴(kuò)展點(diǎn)RequestInterceptor來(lái)實(shí)現(xiàn)的

          發(fā)送請(qǐng)求之前,從TLogContext獲取到traceId,將traceId等信息添加到請(qǐng)求頭中,然后就可以通過(guò)Http請(qǐng)求將traceId等信息傳遞。

          當(dāng)被調(diào)用方接收到請(qǐng)求之后,會(huì)經(jīng)過(guò)TLogWebInterceptor這個(gè)攔截器進(jìn)行攔截,從請(qǐng)求頭中獲取到這些參數(shù),設(shè)置到TLogContext中。

          3、對(duì)常用Http框架的支持

          除了一些RPC框架,TLog也對(duì)一些Http框架進(jìn)行了適配,比如

          • HttpClient
          • Okhttp
          • hutool-http
          • RestTemplate
          • forest

          使用這些Http框架也可以實(shí)現(xiàn)traceId的傳遞

          其實(shí)這些框架的適配跟Feign的適配都是大同小異,都是基于這些Http框架各自提供的擴(kuò)展點(diǎn)進(jìn)行適配的,將traceId等信息放到請(qǐng)求頭中,這里都不舉例了,具體的使用方法可以在官網(wǎng)查看。

          4、對(duì)SpringCloud Gateway的支持

          同樣的,TLog也適配了SpringCloud Gateway

          原理也是一樣的,就是適配了Gateway的GlobalFilter,從請(qǐng)求頭中獲取traceId等信息。

          除了適配了Gateway網(wǎng)關(guān),TLog也適配了Soul網(wǎng)關(guān)。

          5、對(duì)MQ的支持

          對(duì)于MQ的支持跟異步線程差不多,需要將你發(fā)送的消息包裝成TLogMqWrapBean對(duì)象

          TLogMqWrapBean

          發(fā)送的時(shí)候直接發(fā)送TLogMqWrapBean對(duì)象過(guò)去

          TLogMqWrapBean<BizBean> tLogMqWrap = new TLogMqWrapBean(bizBean);
          mqClient.send(tLogMqWrap);

          TLogMqWrapBean會(huì)將traceId等信息攜帶,消費(fèi)者接受到TLogMqWrapBean,然后通過(guò)TLogMqConsumerProcessor處理業(yè)務(wù)消息。

          TLogMqConsumerProcessor.process(tLogMqWrapBean, new TLogMqRunner<BizBean>() {
              @Override
              public void mqConsume(BizBean o) {
               //業(yè)務(wù)操作
              }
          });

          如此就實(shí)現(xiàn)了traceId通過(guò)MQ傳遞。

          在實(shí)際使用中,根據(jù)不同的MQ的類型,可以將消息包裝成TLogMqWrapBean對(duì)象的過(guò)程和處理消息的過(guò)程做統(tǒng)一的封裝處理,以減少發(fā)送消息和處理消息對(duì)于TLog的耦合。

          6、對(duì)任務(wù)框架的支持

          TLog主要是支持一下四種任務(wù)框架

          • JDK Timer
          • Quartz框架
          • spring-scheduled
          • XXL-JOB框架

          其中,spring-scheduled和XXL-JOB在SpringBoot環(huán)境底下是無(wú)需任務(wù)配置的,只需要引入依賴即可。

          Timer在使用的時(shí)候需要將任務(wù)包裝成TLogTimerTask,Quartz需要把QuartzJobBean替換成TLogQuartzJobBean就可以了。

          小總結(jié)

          其實(shí)從上面的各種適配可以看出,其實(shí)本質(zhì)都是一樣的,就是根據(jù)具體框架的擴(kuò)展點(diǎn),在發(fā)送請(qǐng)求之前從TLogContext獲取到traceId,將traceId等調(diào)用者的信息在請(qǐng)求中攜帶,然后被調(diào)用方解析請(qǐng)求,取出traceId和調(diào)用者信息,設(shè)置到被調(diào)用方服務(wù)中的TLogContext中。

          所以,如果一旦需要遇到官方還未適配的框架或者組件,可以參照上述適配過(guò)程進(jìn)行適配即可。

          最后

          總的來(lái)說(shuō),TLog是一款非常優(yōu)秀的日志追蹤的框架,很適合中小公司使用。這里來(lái)總結(jié)一下TLog的特性

          • 通過(guò)對(duì)日志打標(biāo)簽完成輕量級(jí)微服務(wù)日志追蹤
          • 提供三種接入方式:javaagent完全無(wú)侵入接入,字節(jié)碼一行代碼接入,基于配置文件的接入
          • 對(duì)業(yè)務(wù)代碼無(wú)侵入式設(shè)計(jì),使用簡(jiǎn)單,10分鐘即可接入
          • 支持常見(jiàn)的log4j,log4j2,logback三大日志框架,并提供自動(dòng)檢測(cè),完成適配
          • 支持dubbo,dubbox,feign三大RPC框架
          • 支持Spring Cloud Gateway和Soul網(wǎng)關(guān)
          • 支持HttpClient和Okhttp等http調(diào)用框架標(biāo)簽傳遞
          • 支持多種任務(wù)框架,JDK的TimerTask,Quartz,XXL-JOB,spring-scheduled
          • 支持日志標(biāo)簽的自定義模板的配置,提供多個(gè)系統(tǒng)級(jí)埋點(diǎn)標(biāo)簽的選擇
          • 支持異步線程的追蹤,包括線程池,多級(jí)異步線程等場(chǎng)景
          • 幾乎無(wú)性能損耗,快速穩(wěn)定,經(jīng)過(guò)壓測(cè),損耗在0.01%

          由于本文篇幅有限,無(wú)法全面對(duì)TLog進(jìn)行講解,如果想深入了解該框架,可自行閱讀官網(wǎng)或者源碼。

          官網(wǎng):https://tlog.yomahub.com
          github地址:https://github.com/dromara/TLog


          程序汪資料鏈接

          程序汪接的7個(gè)私活都在這里,經(jīng)驗(yàn)整理

          Java項(xiàng)目分享  最新整理全集,找項(xiàng)目不累啦 07版

          堪稱神級(jí)的Spring Boot手冊(cè),從基礎(chǔ)入門到實(shí)戰(zhàn)進(jìn)階

          臥槽!字節(jié)跳動(dòng)《算法中文手冊(cè)》火了,完整版 PDF 開(kāi)放下載!

          臥槽!阿里大佬總結(jié)的《圖解Java》火了,完整版PDF開(kāi)放下載!

          字節(jié)跳動(dòng)總結(jié)的設(shè)計(jì)模式 PDF 火了,完整版開(kāi)放下載!

          歡迎添加程序汪個(gè)人微信 itwang009  進(jìn)粉絲群或圍觀朋友圈

          瀏覽 29
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  97视频国产 | 大屌在线视频 | 天堂a√| 男女日逼视频 | 免费在线观看黄色片 |