Java 整合 Jaeger(分散式追蹤系統)實作
1. Jaeger 介紹
Jaeger 是 CNCF 的項目之一,由 Uber 開放源始碼的一個分散式追蹤系統,並且相容於 OpenTracing API。可用於追蹤微服務架構,聚合來自各個異構系統的即時觀察數據,可以用於監控交易、服務依賴分析程,以及性能/延遲優化。
2. 為什麼要使用分散式追蹤系統?
使用分散式追蹤系統,可以將需要觀察、追蹤的應用、服務...等架構中節點,透過共通的標準,將資訊匯整到一起。當資訊由不同的節點蒐集起來後,即能夠在相同的介面或數據集進行監控及分析,由於資料已經被整理為同質的資訊,也能夠進行比較、效能評估、事務追蹤。
結合 Kafka 快取緩衝機制的架構
3. Jaeger 應用實作
3.1. Docker 安裝 Jaeger
使用 Docker 來執行 Jaeger,可以在本機快速建立環境供驗證使用。
$ docker run -d --name jaeger \
-e COLLECTOR_ZIPKIN_HOST_PORT=:9411 \
-p 5775:5775/udp \
-p 6831:6831/udp \
-p 6832:6832/udp \
-p 5778:5778 \
-p 16686:16686 \
-p 14268:14268 \
-p 14250:14250 \
-p 9411:9411 \
jaegertracing/all-in-one:1.24
相關 Port 所提供服務:
執行起來後,可由以下 url 瀏覽 Jaeger UI:
3.2. 透過 Jaeger Client 推送 trace 到 Jaeger
在 Java 應用中有以下三種方式可進行
這邊實作採用侵入性最低的 java-specialagent 方式,它利用 Java 提供的 javaagent (Oracle docs - instrument) 機制,掛載 agent lib (Maven 下載 binary jar) 來採集資訊,透過在執行 Java 應用時加上如下 vm argument,即可快速達成代理推送資訊的目的。詳細的 argument 可參考 GitHub)。
-javaagent:opentracing-specialagent-1.7.4.jar
-Dsa.exporter=jaeger
-DJAEGER_ENDPOINT="http://localhost:14268/api/traces"
-DJAEGER_SAMPLER_TYPE=const
-DJAEGER_SAMPLER_PARAM=1
-DJAEGER_SERVICE_NAME="bpmutils"
-DJAEGER_PROPAGATION=b3
3.3. 使用 Jaeger 觀察 trace 資訊
利用網址 http://localhost:16686/ 瀏覽 Jaeger,查詢 trace 紀錄。
其中資訊的組成如下:
- Trace:貫穿一個分散式系統的事務追蹤描述。
- Span:一個被命名的請求操作與時間紀錄,如:一個 Http GET 請求;Span 有嵌套關系,如果一個請求會調用其它服務,就會生成子 Span。
- Tag:一組由 <key, value> 構成的標簽集合。它包含許多有用訊息,如:請求方法、請求 URL、返回狀態碼等。
- Log:一組 Span 的日誌集合。
3.3.1. Trace 如下圖中的一筆資料 (bpmutils:completeTask,由 49 筆 Spans 組成)
3.3.2. Span 如下圖紅框中條列的各個 Service & Operation,每筆 Span 中可查看藍框中詳細 Tags、Logs 等資訊
到這裡為止,已經簡單完成了分散式追蹤系統的體驗。
4. 後記
4.1. 提供豐富的模組支援常用 Java 套件
利用 javaagent 機制提供的 java-specialagent,其提供相當豐富的模組 Integrations,如:Apache HttpClient、Java JDBC API、Java Servlet API、Spring xxx...等常用套件的 trace 模組。詳細可參考 GitHub)。
例如透過以下 vm argument 先關閉全部 integration,再指定啟用 servlet、jdbc 兩個模組。
-Dsa.integration.*.disable=true -Dsa.integration.servlet.enable=true -Dsa.integration.jdbc.enable=true
4.2. Jaeger Client 推送 trace 的小阻礙
測試過程中,以 javaagent 並未指定 integration 啟動數次服務,觀察發現除了 servlet 外,其餘 integration rule 似乎未立即生效,如下圖 Traces 泡泡圖所示,在紅箭頭所示時間點約半小時候後,到藍色箭頭時間點位置開始才有密集的 rule 生效並進行收集。
若採用前述指定 servlet、jdbc 模組方式,則一開始就推送 trace 資訊,而不會有未立即生效問題。
4.3. java-specialagent 支援動態掛載 (Dynamic Attach) 的機制
在 Java 應用啟動後,透過掛載指定應用 PID 的方式,動態連接 javaagent 到目標應用上,此方式讓追蹤資訊的收集更靈活。
- jdk1.8
java -Xbootclasspath/a:$JAVA_HOME/lib/tools.jar -jar opentracing-specialagent-1.7.4.jar ${PID}
- jdk9+
java -jar opentracing-specialagent-1.7.4.jar ${PID}
5. 參考
補充4.3.動態掛載機制實測,使用jdk1.8測試如以下,即可將已經在運行的「BPMUtilsApplication」服務加進蒐集資訊的行列了:
❯ jps
44624
8615 Launcher
8617 BPMUtilsApplication
444 MacLauncher
8622 Jps
❯ java -Xbootclasspath/a:/Library/Java/JavaVirtualMachines/zulu-8.jdk/Contents/Home/lib/tools.jar -Dsa.exporter=jaeger -Dwf.service=delivery -DJAEGER_SERVICE_NAME="bpmutils" -jar /Users/user/Downloads/opentracing-specialagent-1.7.4.jar 8617