開源框架TLog核心原理架構解析
前言
最近在做TLog 1.2.5版本的迭代,許多小夥伴之前也表示說很想參與開源項目的貢獻。為了讓項目更好更快速的迭代新特性以及本著發揚開源精神互相學習交流,很有幸招募到了很多小夥伴與我一起前行。
為了方便大家理解TLog項目的核心原理和架構,便有了此篇內容。此篇內容偏向TLog技術設計和核心原理,同時也涵蓋著做一個開源框架所需要考慮的問題和技術要點。
我一直相信,好的技術內容應提領關鍵點,引導大家該去如何讀懂源碼。而不是全篇的貼程式碼。所以此篇也不是源碼解析,而是提煉關鍵點,讓大家如何的更好去理解。
因為閱讀者在某些點上可能會有知識盲區,為了講了細緻,在某些點上我儘可能附加了延伸閱讀。知道相關知識點的同學,可以直接跳過。
還有,如果你是第一次閱讀到此篇內容,不知道TLog是什麼項目,則可以移步Gitee的託管倉庫以及項目主頁去查看項目特性:
gitee託管倉庫://gitee.com/dromara/TLog
github託管倉庫: //github.com/dromara/TLog
項目主頁: //yomahub.com/tlog/
你也可以看之前發布的一篇介紹TLog文章
模組
了解一款開源框架,首先從模組開始了解,TLog定位是一款輕量級日誌追蹤框架,它由10個模組組成
首先TLog既然是一款日誌框架,日誌增強就是它的核心,得適配主流的日誌框架(log4j / log4j2 /logback),這些最主要的邏輯和最核心的功能實現都在tlog-core
模組中(以後可能還會單獨拆出3個日誌框架的單獨模組)。
其次,TLog能夠進行日誌追蹤,自然要適配微服務架構,支援RPC框架/協議(dubbo / dubbox / spring cloud feign / http)。由於每種RPC框架有自己的擴展點,自然不可能抽象寫出統一的處理邏輯。所以就有了以下模組:
tlog-dubbo
為對接apache dubbo的適配模組
tlog-dubbox
為對接早期的噹噹的dubbox開源版本,因為有的公司還在用
tlog-feign
為對接spring cloud feign的適配模組
tlog-webroot
為對接最普通的http調用適配模組
考慮到用spring cloud的很多公司都會用spring全家桶的spring cloud gateway,所以就有了適配spring cloud gateway的適配模組tlog-gateway
在spring支援方面,tlog支援了傳統spring的xml配置結構,也支援了springboot的自動裝配。由於spring是springboot的子集,所以必定有2個模組,所以就有了tlog-all
和tlog-all-springboot-starter
。之所以要加上all字樣,因為這2個包也是開發者引用的門麵包,這2個提供單獨的依賴地址,會把所需要其他的tlog包一起依賴帶入。這樣就不用一個個去聲明依賴了。
TLog提供了基於javaagent的無依賴使用方式,所以就有了tlog-agent
模組。在打包時,會單獨打成一個jar包。
其他tlog模組所公共使用的一些VO,枚舉,util類則抽出來形成一個單獨的模組,所以就有了tlog-common
。
模組之間的依賴關係圖如下:
啟動裝載
TLog大約有80%的工作都是啟動時完成的,所以第一步就要弄清楚TLog隨著項目啟動時幹了些什麼。
由於springboot有自動裝配功能,所以只需要弄清楚tlog-all-springboot-starter
自動裝配了什麼,就可以了解非springboot項目那些手動配置xml的意義了。
不清楚springboot自動裝配功能的同學,可以先去了解下這塊的知識,我覺得這篇文章講的比較透徹,可以延伸閱讀下:
TLog在springboot環境下所有自動裝配的配置類,都在spring.factories
中體現:
org.springframework.boot.autoconfigure.EnableAutoConfiguration=\
com.yomahub.tlog.springboot.TLogPropertyConfiguration,\
com.yomahub.tlog.springboot.TLogWebAutoConfiguration,\
com.yomahub.tlog.springboot.TLogFeignAutoConfiguration,\
com.yomahub.tlog.springboot.TLogAspectAutoConfiguration,\
com.yomahub.tlog.springboot.TLogCommonAutoConfiguration,\
com.yomahub.tlog.springboot.TLogGatewayAutoConfiguration
TLogPropertyConfiguration
主要用來自動裝配的是TLog配置初始化器,最終注入的是TLogPropertyInit
,在傳統spring環境下,也只需要單獨配置TLogPropertyInit
的xml就可以了,所以兩種spring環境形成最終的統一。
TLogWebAutoConfiguration
主要用來自動裝配http協議的攔截器。
TLogFeignAutoConfiguration
主要用來自動裝配spring cloud feign環境下的攔截過濾器。
TLogAspectAutoConfiguration
主要用來自動裝配自定義標籤的切面,spring會自動為切中的類生成動態代理注入上下文。
TLogCommonAutoConfiguration
主要用來自動裝配基於spring上下文的工具類。在很多不在spring容器管理中的bean想獲取spring上下文中的bean時,都會用到這個工具類。
TLogGatewayAutoConfiguration
主要用來自動裝配spring cloud gateway環境下的攔截過濾器。
只要註冊了以上的自動裝配類,在springboot環境下,啟動時都會幫你自動裝配好。但是在傳統spring下,你還是得在xml中一個個的配置。所以開源項目支援springboot是很有必要的。
這些自動裝配的順序,也並不是按照配置的順序進行的,有先後依賴關係。具體可以仔細研究源碼,源碼注釋有寫。
如果有人不知道如何控制springboot自動裝配的順序的話 ,推薦看我之前寫的一篇文章,專門針對這個知識點進行了解讀
那不知道會不會有人問,那dubbo/dubbox,三大日誌框架的增強就不需要註冊自動裝配器么?
這裡一一解釋:
dubbo/dubbox,在設計時就有基於spi的實現,能夠自動識別出擴展的插件,所以無需註冊任何bean到spring容器,所以不需要裝配。
log4j&logback,位元組碼模式的話,在springboot/spring啟動前就得載入了。下文會說到。所以不在springboot/spring啟動階段裝配。至於日誌適配模式,由於需要開發者提前替換好相關的encoder,所以日誌框架在載入日誌配置文件時就會做這件事。所以也不需要自動裝配任何東西。
log4j2的設計完全採用插件式,他自己能掃描並識別到相關擴展插件,所以也不需要在springboot/spring裝配時干任何事。
Log框架的支援解析
對於log框架的支援是TLog的重點,主要都在tlog-core
這個模組中。TLog接入有三種方式,javaagent接入,位元組碼接入,適配模式接入。接入方式和對應的類,有下圖:
其實可以發現,javaagent本質上也是利用位元組碼的方式進行,區別是,javaagent的jar包外置,不用項目依賴。而位元組碼方式,需要依賴,並且要在啟動類裡面手動添加AspectLogEnhance.enhance()
程式碼進行觸發。
還可以發現,javaagent模式和位元組碼模式目前是不支援非同步日誌的。只有適配模式才能支援。
可能會有人有疑問,上圖為什麼沒提到log4j2呢。
答:因為之前也說了,log4j2是插件形式,從本質上來講。log4j2的生效方式只有一種,log4j2自動會去檢測插件,嚴格的說,log4j2日誌增強的方式不屬於上面任何一種。也不需要任何裝配,任何觸發條件,只需要定義相關插件就可以了。具體log4j2的插件定義在tlog-core
的如下包里:
com.yomahub.tlog.core.enhance.log4j2
Log框架中的MDC
TLog對3大日誌框架的MDC也有支援,具體三個支援類在以下路徑
log4j: com.yomahub.tlog.core.enhance.log4j.AspectLog4jMDCPatternConverter
logback: com.yomahub.tlog.core.enhance.logback.AspectLogbackMDCConverter
log4j2: com.yomahub.tlog.core.enhance.log4j2.AspectLogLog4j2MDCConverter
要注意的是,這3個類,並不是直接對MDC作處理,這3個類的作用是:檢測log配置是否用了MDC
如果檢測到配置文件有用mdc,則在TLog執行緒上線文中設置一個標記
TLogContext.setHasTLogMDC(true);
而真正對MDC進行處理的是這個類TLogRPCHandler
,這個類是所有rpc調用的一個抽象層,裡面有以下程式碼進行了MDC的處理邏輯:
...
//如果有MDC,則往MDC中放入日誌標籤
if (TLogContext.hasTLogMDC()) {
MDC.put(TLogConstants.MDC_KEY, tlogLabel);
}
如果這個標記為true,則用slf4j的MDC API進行設值
RPC支援
TLog對於RPC的支援,主要用到的是各個RPC框架自己的攔截器和過濾器來實現。
dubbo/dubbox
dubbo和dubbox是使用dubboFilter來實現,其原理2者一致。程式碼也都差不多。因為包路徑和個別類命名有區別,所以分成了2個模組,這裡放在一起講
其主要的處理類為TLogDubboFilter
和TLogDubboxFilter
,之前有提到過,dubbo/dubbox有自己的SPI,能檢測出插件。定義dubbo的插件方式如下:
@Activate(group = {CommonConstants.PROVIDER, CommonConstants.CONSUMER}, order = -10000)
public class TLogDubboFilter extends TLogRPCHandler implements Filter {
...
}
dubbo/dubbox這裡分provider端和consumer端去處理,A->B,A就是consumer,B就是provider。2端的處理邏輯不一樣。
provider端:接受隱式傳參里的參數–>處理參數–>放入tlog的執行緒上下文–>調用原有業務邏輯
consumer端:從tlog執行緒上下文中獲得參數–>處理參數–>調用遠端業務邏輯
feign/http
在spring cloud feign的場景,一般用feign作為consumer,普通的controller作為provider。所以這2個放到一起講。
feign主要的處理類為TLogFeignFilter
,作為consumer端,大致做了如下事情:
從tlog執行緒上下文中獲得參數–>參數處理–>放入http header–>請求http
而Controller處理類主要為TLogWebInterceptor
,作為provider端,大致做了如下事情:
從http header中接受到標籤參數–>處理參數–>放入tlog執行緒上下文–>調用原有業務邏輯
自定義標籤
自定義標籤是TLog中一個特色功能模組,能讓用戶自己定義標籤編入log日誌中。
其主要的處理類就一個aop,為AspectLogAop
,位置在tlog-core
中。
其主要思想就是去切@TLogAspect
標籤,然後解析相關參數,最後把結果append到執行緒上下文的標籤值中。
這裡面涉及了標註的解析,點操作符的解析和值的獲取等操作。想弄明白,直接看AspectLogAop
這個類就可以了。
其他功能
TLog還有其他輔助功能。
對mq中間件的支援:程式碼在tlog-core
的com.yomahub.tlog.core.mq
這個包中
自動列印參數和調用時間:在RPC的filter下面,會有XxxInvokeTimeFilter
類
非同步執行緒支援/執行緒池的支援:程式碼在tlog-core
的com.yomahub.tlog.core.thread
中
自定義TraceId生成器:程式碼在tlog-common
的com.yomahub.tlog.id
中
以上所有功能的程式碼理解,結合著使用文檔去閱讀理解,應該很容易弄懂,就不作解讀了
關於我
我是一個開源作者,也是一名內容創作者。「元人部落」是一個堅持做原創的技術科技分享號,會一直分享原創的技術文章,陪你一起成長。