?既生瑜,何生亮,SkyWalking 和 ELK 實(shí)現(xiàn)鏈路追蹤的實(shí)踐
圖片
一、背景
最近在給項(xiàng)目搭建日志平臺(tái)的時(shí)候,采用的方案是 SkyWalking + ELK 日志平臺(tái),但發(fā)現(xiàn) ELK 日志平臺(tái)中的日志沒有 Trace ID,導(dǎo)致無(wú)法追蹤代碼報(bào)錯(cuò)的整體鏈路。
空哥提示:Trace ID 是分布式追蹤中用來(lái)唯一標(biāo)識(shí)一個(gè)服務(wù)請(qǐng)求或事務(wù)的 ID。在微服務(wù)架構(gòu)中,一個(gè)請(qǐng)求可能會(huì)經(jīng)過多個(gè)服務(wù)節(jié)點(diǎn),Trace ID 幫助追蹤和關(guān)聯(lián)整個(gè)請(qǐng)求鏈路中的所有日志和性能數(shù)據(jù)。
既然 SkyWalking 提供了日志的鏈路追蹤,為什么 ELK 沒有鏈路追蹤 ID 呢? 帶著這個(gè)疑問我們繼續(xù)往下看。
二、SkyWalking 和 ELK 啥關(guān)系啊?
- SkyWalking: 專注于應(yīng)用性能監(jiān)控(APM)的系統(tǒng),主要提供分布式追蹤、服務(wù)性能分析和多維度監(jiān)控功能。
它支持自動(dòng)化代碼埋點(diǎn),能夠追蹤微服務(wù)之間的調(diào)用關(guān)系和性能指標(biāo)。 - ELK:日志數(shù)據(jù)的集中管理和分析,Elasticsearch + Logstash + Filebeat,作為日志采集和存儲(chǔ),Kibana 作為可視化日志檢索平臺(tái)。
SkyWalking 和 ELK 是如何聯(lián)系在一起的?我們一步一步往下看。
2.1 SkyWalking
SkyWalking 本來(lái)就帶有鏈路追蹤,而且通過搭建 SkyWalking-UI 服務(wù)就可以以通過界面來(lái)查看日志。
圖片
SkyWalking 整體架構(gòu)如下:
圖片
FROM http://skywalking.apache.org/
- 最上面的 Tracing:負(fù)責(zé)從應(yīng)用中,收集鏈路信息,發(fā)送給 SkyWalking OAP 服務(wù)器,目前支持 SkyWalking、Zikpin、Jaeger 等提供的 Tracing 數(shù)據(jù)信息。我們采用的是 SkyWalking Agent 收集 SkyWalking Tracing 數(shù)據(jù),傳遞給 SkyWalking OAP 服務(wù)器。
- 中間的 SkyWalking OAP 服務(wù)器 :負(fù)責(zé)接收 Agent 發(fā)送的 Tracing 數(shù)據(jù)信息,然后進(jìn)行分析(Analysis Core) ,存儲(chǔ)到外部存儲(chǔ)器( Storage ),最終提供查詢( Query )功能。
- 最右邊的 Storage :負(fù)責(zé)存儲(chǔ) Tracing 數(shù)據(jù)。目前支持 ES、MySQL、Sharding Sphere、TiDB、H2 多種存儲(chǔ)器。
- 最左邊的 SkyWalking UI :一個(gè)網(wǎng)頁(yè)版的界面,提供查看數(shù)據(jù)的功能。
2.2 ELK 集中日志平臺(tái)
整體的架構(gòu)圖如下所示,
圖片
流程如下:
- Beats:
Filebeat 服務(wù)屬于 Beats,部署在應(yīng)用側(cè),它把日志收集起來(lái),然后再把數(shù)據(jù)傳給 Logstash 服務(wù)。 - Logstash:
負(fù)責(zé)日志數(shù)據(jù)的過濾、匹配、格式轉(zhuǎn)換,然后將日志數(shù)據(jù)發(fā)送給 Elasticsearch 存儲(chǔ)。 - Elasticsearch:
負(fù)責(zé)存儲(chǔ)日志數(shù)據(jù)和建立日志數(shù)據(jù)索引,便于 Kibana 查詢?nèi)罩尽?/li> - Kibana:
負(fù)責(zé)可視化查詢?nèi)罩緮?shù)據(jù)。
2.3 SkyWalking 和 ELK 有什么相同之處?
- 都能采集日志
- 都有可視化界面來(lái)查詢?nèi)罩?/li>
那么這兩款日志平臺(tái)有很多類似之處,直接用其中一種不行嗎?
三、只用 SkyWalking 可以嗎?
SkyWalking 優(yōu)點(diǎn)是服務(wù)性能分析和鏈路追蹤,但也有不足之處。
3.1 采集方式上不足
Skywalking 監(jiān)控 Java、Golang、Node、.NET 語(yǔ)言的鏈路都是采用了 SDK 或者 Agent 的方式將數(shù)據(jù)上報(bào)到 Skyalking 后端,不過都是采用 gRPC 的方式和后端交互,比如我們項(xiàng)目是 Java 項(xiàng)目,SkyWalking Agent 采集到后端的 Java 日志后進(jìn)行上報(bào)。而對(duì)于 Nginx 則需要寫 Lua 腳本來(lái)和 SkyWalking AOP 服務(wù)通信,對(duì)于 MySQL 日志也需要單獨(dú)寫腳本來(lái)上報(bào)日志。
3.2 數(shù)據(jù)可視化的不足
- SkyWalking 對(duì)于鏈路的展示非常直觀,但是對(duì)于日志的數(shù)據(jù)的展示探索能力很弱,而 Kibana 提供了豐富的可視化選型,如折線圖、餅圖等。
- SkyWalking 對(duì)于日志的搜索和展示能力較弱,而 Kibana 對(duì)于搜索的方式非常豐富,而且支持高亮。
下圖分別為 SkyWalking 和 Kibana 的可視化界面
圖片
圖片
四、只用 ELK 可以實(shí)現(xiàn)鏈路追蹤嗎?
當(dāng)然是可以,但是 ELK 并沒有日志追蹤的能力,需要借助其他工具來(lái)實(shí)現(xiàn),以下是常見的做法。
- SkyWalking 嵌入 Trace ID,依賴 SkyWalking Agent。
- MDC 中加入 Trace ID,簡(jiǎn)便,需要在攔截器中加入 Trace ID。
- Kibana 最近日志,不準(zhǔn)確。
4.1 SkyWalking 嵌入 Trace ID 到日志
通過 SkyWalking 的自定義日志布局類 TraceIdPatternLogbackLayout,將分布式追蹤系統(tǒng)中的追蹤 ID(Trace ID)嵌入到日志中。
4.1.1 使用方式
在 logback-spring.xml 日志配置文件中配置控制臺(tái)打印的時(shí)候使用帶有 SkyWalking 的 TraceId 的日志布局。如下代碼所示,使用了 TraceIdPatternLogbackLayout 日志布局,然后在日志格式中加入了 [%tid],就能將 trace id 打印出來(lái)。
<configuration>
<appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
<encoder>
<pattern>%d{yyyy-MM-dd HH:mm:ss} [%thread] %-5level %logger{36} - %msg%n</pattern>
</encoder>
</appender>
<!-- 定義一個(gè)帶有TraceId的日志布局 -->
<layout class="org.apache.skywalking.apm.toolkit.log.logback.v1.x.TraceIdPatternLogbackLayout">
<pattern>${CONSOLE_LOG_PATTERN:-%clr(%d{${LOG_DATEFORMAT_PATTERN:-yyyy-MM-dd HH:mm:ss.SSS}}){faint} %clr(${LOG_LEVEL_PATTERN:-%5p}) [%tid] %clr(${PID:- }){magenta} %clr(---){faint} %clr([%15.15t]){faint} %clr(%-40.40logger{39}){cyan} %clr(:){faint} %m%n${LOG_EXCEPTION_CONVERSION_WORD:-%wEx}}</pattern>
</layout>
<root level="debug">
<appender-ref ref="STDOUT" />
</root>
</configuration>
程序運(yùn)行期間就會(huì)在控制臺(tái)窗口打印出 trace id,如下所示:
圖片
然后通過 Filebeat 和 Logstash 將日志采集并上傳到 Elasticsearch。如下圖索索,Kibana 根據(jù) trace id 來(lái)查看鏈路日志。
圖片
4.1.2 原理
- 上下文傳遞:
在分布式系統(tǒng)中,服務(wù)之間通過 HTTP 調(diào)用或其他通信機(jī)制相互交互。
Trace ID 需要在服務(wù)之間傳遞,以便追蹤整個(gè)請(qǐng)求鏈路。 - 日志集成:
SkyWalking 通過字節(jié)碼增強(qiáng)或自動(dòng)代理等技術(shù),自動(dòng)在應(yīng)用的運(yùn)行時(shí)上下文中生成和管理 Trace ID。 - 配置靈活性:
SkyWalking 允許開發(fā)者通過配置文件(如 logback.xml)自定義日志格式,包括是否在日志中包含 Trace ID。
4.2 MDC 方案
MDC 的方案就是自己生成一個(gè)隨機(jī) ID 作為 traceId,然后 put 到 MDC 里面。如下代碼所示:
MDC.put("traceId", UUID.randomUUID().toString());
MDC(Mapped Diagnostic Context)用于存儲(chǔ)運(yùn)行上下文的特定線程的上下文數(shù)據(jù)。MDC 主要依賴于線程局部存儲(chǔ)(Thread-Local Storage),這意味著每個(gè)線程都有自己獨(dú)立的 MDC 數(shù)據(jù)。屬于該線程的任何代碼都可以輕松訪問線程的 MDC 中存在的值。
先貼個(gè)原理圖給大家看看:
4.3 Kibana 的最近日志
Kibana 可查看某一條日志相近的多條日志,如下圖所示,點(diǎn)擊 View surrounding documents 按鈕即可。
圖片
然后就能看到與之時(shí)間相近的多條日志。
圖片
但是這種方式不易準(zhǔn)確辨別出相關(guān)聯(lián)的上下文的日志。不易辨別的原因如下:
- 相近時(shí)間段內(nèi)有很多類似日志。
- 相近時(shí)間段內(nèi)有大量的其他日志穿插在這個(gè)上下文中,不易刷選可用的日志。
五、總結(jié)
SkyWalking和 ELK 各自在 APM 與日志管理領(lǐng)域發(fā)揮著重要作用,盡管原生 ELK 不直接支持鏈路追蹤,但通過與 SkyWalking 的集成,可以互補(bǔ)優(yōu)勢(shì),共同提升微服務(wù)架構(gòu)下的可觀測(cè)性。