歡迎訪問我的GitHub
https://github.com/zq2599/blog_demos
內容:所有原創文章分類匯總及配套源碼,涉及Java、Docker、Kubernetes、DevOPS等;
關於采樣(Sampling)
-
采樣很好理解:使用Jaeger時,未必需要將所有請求都上報到Jaeger,有時候只要抽取其中一部分觀察即可,這就是按照一定策略進行采樣;
-
Jaeger SDK是支持多種采樣配置的,在分布式系統中,他們遵循的原則是前置判定(consistent upfront 或者head-based),簡單來說,假如consumer服務調用provider服務,那么某一次請求只要consumer決定不采樣,那么provider在處理這個請求的時候也不會采樣,也就是說對於一次完整的trace,只要最前面的服務不上報到jaeger,那么整個trace后面涉及的服務都不會上報到jaeger
-
Jaeger采樣配置分為客戶端和服務端兩種配置,默認用的是服務端配置
-
本文咱們來了解如何在客戶端(也就是接入Jaeger的應用)配置采樣,並且動手驗證效果,常用的客戶端采樣策略有以下三種:
- 固定:要么全部采樣,要門全部不采樣
- 比例:按照指定比例采樣
- 限速:固定時間周期內采樣固定數量,例如每秒一個
- 接下來,逐個配置和體驗這三種采樣的效果
關於實戰用的工程
- 采樣配置實戰不涉及編碼,只需要改一些配置,所以沒必要大張旗鼓的新建工程寫代碼,用《Jaeger開發入門(java版)》一文中的兩個maven子工程即可:服務提供方jaeger-service-provider和服務調用方jaeger-service-consumer,都做成docker鏡像,用docker-compose啟動,網絡架構如下圖:

- 請確保項目的日志模板中已添加了traceId、spanId、sampled等變量,如下圖紅框所示,有了這些配置,咱們在日志中就能看到對應的trace是否被采樣(這一步非常重要):

- 為了方便修改代碼后重新部署啟動,我寫了個名為full.sh的shell腳本文件,運行即可將修改后的代碼制作成最新的鏡像並用docker-compose運行起來:
#!/bin/bash
echo "停止docker-compose"
cd jaeger-service-provider && docker-compose down && cd ..
echo "編譯構建"
mvn clean package -U -DskipTests
echo “創建provider鏡像”
cd jaeger-service-provider && docker build -t bolingcavalry/jaeger-service-provider:0.0.1 . && cd ..
echo “創建consumer鏡像”
cd jaeger-service-consumer && docker build -t bolingcavalry/jaeger-service-consumer:0.0.1 . && cd ..
echo "清理無效資源"
docker system prune --volumes -f
echo "啟動docker-compose"
cd jaeger-service-provider && docker-compose up -d && cd ..
- 如果您用的是IDEA,在下圖紅框位置添加一個自定義命令,選中上述shell文件,就可以在IDEA中用run命令來編譯構建部署了:

- 現在准備工作已經完成,開始實戰吧,從最簡單的固定采樣開始;
固定采樣
-
固定采樣的邏輯很簡單:要么全部上報,要么一個也不報
-
固定采樣的配置方式如下圖紅框所示:

-
要注意的是:根據前置判定(consistent upfront 或者head-based)原則,只要將上述配置寫入jaeger-service-consumer項目的配置文件即可,至於jaeger-service-provider維持原狀不做任何改動
-
執行前面寫的full.sh腳本,編譯構建部署
-
瀏覽器訪問http://localhost:18080/hello,產生一些web請求,多訪問幾次
-
看jaeger-service-consumer容器的日志,如下圖,紅框中的sampled=false表示未采樣,三此請求的日志都是如此:

- 再看jaeger-service-provider容器的日志,如下圖紅框,也全部都沒有采樣,這證明Jaeger的前置判定原則(consistent upfront 或者head-based)是准確的,jaeger-service-consumer是一次trace的源頭,被它關閉了采樣的trace,在后續的服務中也會自動關閉采樣:

- 去Jaeger的web頁面看看,空空如也,連服務列表中都沒有jaeger-service-consumer和jaeger-service-provider:

- 試過了全部不采樣,再來試試全部采樣的配置,如下圖紅框:

- 重新部署,再產生幾次請求,去看jaeger-service-consumer容器的日志,如下圖紅框,全部都被采樣了:

- 去看jaeger-service-provider容器的日志,也是如此,所有trace都被采樣:

- 打開Jaeger的web頁面,可見jaeger-service-consumer的三次請求對應的trace全部上報:

- 至此,最簡單的固定采樣已完成,來看看更實用的比例采樣
比例采樣
- 顧名思義,就是按照一定的百分比采樣,配置如下圖所示:

-
執行前面寫的full.sh腳本,編譯構建部署
-
測試比例采樣的方法就是發多個請求,檢查采樣的trace是否是總數的十分之一,我這里用jmeter來執行多次請求,您可以選擇自己擅長的工具,或者寫代碼寫腳本,甚至手動訪問多次
-
使用jmeter可以控制請求次數,用的是Loop Controller,如下圖紅框所示:

- 向jaeger-service-consumer的/hello接口發送完一百次請求后,可以從docker容器日志中檢查采樣情況,這里使用grep和wc命令的組合來統計日志中出現sampled=true和sampled=false的行數,完整的命令如下:
docker logs jaeger-service-consumer| grep 'sampled=true'|wc -l
- 100個請求,采樣率百分之十,但是用上述命令得到的結果並不是精確值10,而是8,再統計未采樣的日志行數(把true改成false),得到的結果是92,總數對得上,但是采樣數並非精確的百分之十,如下圖:

- 然后將請求總數增加到一千條,得到的采樣比例接近百分之十,如下:

- 打開Jaeger的web頁面,可見果然只有106個trace:

- 比例采樣完成了,接下來是限速采樣
限速采樣
- 關於限速,似乎不夠具體不便於理解,但是看看官方文檔上的關鍵字leaky bucket,如下圖紅框,聰明的您一定想到了其中的關鍵,漏桶限流算法(注意,是漏桶,不是令牌桶,漏桶算法的峰值和桶大小有關):

- 配置如下圖紅框所示:

-
執行前面寫的full.sh腳本,編譯構建部署
-
咱們的配置是每秒鍾一次采樣,所以驗證的時候要控制好發送請求的時長,我這里還是用jmeter來發請求的,如下圖紅框所示,jmeter有種Runtime Controller類型的控制器,可以控制持續請求的時長,我這里設置為10秒:

- 用jmeter持續發送10秒的請求,從jmeter的匯總報告中可見一共發了70個請求:

- 用命令docker logs jaeger-service-consumer| grep 'sampled=true'|wc -l查看采樣總數,10秒的預期是10個,結果如下,並不精確,只是接近而已:

- 清掉所有數據,將時長改成100秒試試,一共發出次852請求:

- 采樣總數為96,接近預期:

- 打開Jaeger的web頁面也是96次trace:

服務端配置一瞥
-
還記得《分布式調用鏈跟蹤工具Jaeger?兩分鍾極速體驗》、《Jaeger開發入門(java版)》等文章中的操作嗎?那時咱們並沒有添加任何與采樣有關的配置,但是每次請求都能在Jaeger的web頁面上查到對應的trace,也就是說所有請求全部被采樣了,這是為啥?
-
如果配置文件中沒有采樣相關的內容,那么默認使用的就是遠程配置,具體的信息就在jaeger的all-in-one容器中,執行下面這個命令,就能看到遠程采樣配置:
docker exec jaeger cat /etc/jaeger/sampling_strategies.json
- 上述命令可以看到sampling_strategies.json的內容如下,原來服務端的配置是比例采樣,不過比例是百分之百,這就能解釋為何所有請求都能在Jaeger的web頁面查到trace信息了:
{
"default_strategy": {
"type": "probabilistic",
"param": 1
}
}
- 至此,采樣配置實戰已經完成,希望能給您提供一些參考,輔助您針對實際情況定制更加合適的采樣策略
你不孤單,欣宸原創一路相伴
歡迎關注公眾號:程序員欣宸
微信搜索「程序員欣宸」,我是欣宸,期待與您一同暢游Java世界...
https://github.com/zq2599/blog_demos
