一、 概要
當(dāng)前公司后端整體架構(gòu)為:Spring Boot + Dubbo。由于早期項(xiàng)目進(jìn)度等原因,對(duì)日志這塊沒有統(tǒng)一的規(guī)范,基本上是每個(gè)項(xiàng)目自己管自己的日志。這也對(duì)后面的問(wèn)題排查帶來(lái)了很大的困難,特別是那些需要同時(shí)或者多級(jí)調(diào)用Dubbo的服務(wù)場(chǎng)景,排查起來(lái)更加的困難。
現(xiàn)在需要實(shí)現(xiàn)從請(qǐng)求開始,到請(qǐng)求結(jié)束的全程日志跟蹤。需求很簡(jiǎn)單,實(shí)現(xiàn)思路也不難,只需要全局添加一個(gè)traceId即可。
當(dāng)然只有日志的記錄是不夠的,還要有日志的統(tǒng)一存儲(chǔ)和查詢。
二、 思路
2.1 日志采集與存儲(chǔ)
初步選擇的方案是:阿里云*日志服務(wù)??擅饴涞?,直接存儲(chǔ)。日志服務(wù)支持Appender直接發(fā)送。
替代方案:基于Logback appender + 消息隊(duì)列 + ELK來(lái)實(shí)現(xiàn)。不過(guò),這樣的話,成本并不一定會(huì)比阿里云服務(wù)低。
2.2 當(dāng)前項(xiàng)目改造
2.2.1 API接口
當(dāng)前項(xiàng)目返回?cái)?shù)據(jù)格式:
{
"code": 200,
"data": "Hello world",
"msg": "ok"
}
改造后,所有HTTP API響應(yīng)體中增加traceId字段:
{
"code": 200,
"data": "Hello world",
"msg": "ok",
"traceId": "bd41aed8b2da4895a9d2b43d1ef12595"
}
2.2.2 Dubbo
對(duì)于服務(wù)調(diào)用方:每次調(diào)用服務(wù)時(shí),都需要向服務(wù)提供方傳遞traceId。
對(duì)于服務(wù)提供方:每次服務(wù)響應(yīng)時(shí),都需要從服務(wù)調(diào)用方獲取traceId,并將該traceId傳遞下去,直至該響應(yīng)結(jié)束。
2.2.3 日志配置
需對(duì)當(dāng)前日志格式及配置進(jìn)行統(tǒng)一。
2.3 落地思路
2.3.1 API接口
項(xiàng)目?jī)?nèi)部使用org.slf4j.MDC傳遞traceId。
使用攔截器完成traceId的設(shè)置與清除。請(qǐng)求到來(lái)時(shí),生成并設(shè)置traceId;請(qǐng)求結(jié)束時(shí),清除traceId。
攔截器中無(wú)法修改HTTP響應(yīng)體??赏ㄟ^(guò)ControllerAdvice統(tǒng)一向Response Body中寫入traceId。
2.3.2 Dubbo
使用Dubbo提供的org.apache.dubbo.rpc.Filter來(lái)完成traceId的設(shè)置與獲取。
三、 備注
Dubbo日志問(wèn)題
Dubbo服務(wù)的調(diào)用,并不一定是HTTP Request引起的,所以會(huì)存在一些沒有traceId的調(diào)用情況。這塊需要單獨(dú)的處理。
可對(duì)traceId的命名進(jìn)行規(guī)范。
如:
-
req:xxa:xxx表示 前端請(qǐng)求,xxa模塊,序號(hào)標(biāo)識(shí)xxx -
tim:xxc:xxx表示 定時(shí)器觸發(fā),xxc模塊,序號(hào)標(biāo)識(shí)xxx
命名規(guī)范需要根據(jù)具體業(yè)務(wù)來(lái)編寫。示例僅供參考~
并且可對(duì)返回的數(shù)據(jù)進(jìn)行適當(dāng)?shù)奶幚?,使其避免暴露關(guān)鍵信息,同時(shí)還能方便問(wèn)題的定位與處理。當(dāng)然這個(gè)度還是需要根據(jù)具體業(yè)務(wù)和需求來(lái)把握。