天天看點

Jaeger的用戶端采樣配置(Java版)

https://github.com/zq2599/blog_demos

内容:所有原創文章分類彙總及配套源碼,涉及Java、Docker、Kubernetes、DevOPS等;

采樣很好了解:使用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啟動,網絡架構如下圖:

Jaeger的用戶端采樣配置(Java版)

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

Jaeger的用戶端采樣配置(Java版)

為了友善修改代碼後重新部署啟動,我寫了個名為full.sh的shell腳本檔案,運作即可将修改後的代碼制作成最新的鏡像并用docker-compose運作起來:

如果您用的是IDEA,在下圖紅框位置添加一個自定義指令,選中上述shell檔案,就可以在IDEA中用run指令來編譯建構部署了:

Jaeger的用戶端采樣配置(Java版)

現在準備工作已經完成,開始實戰吧,從最簡單的固定采樣開始;

固定采樣的邏輯很簡單:要麼全部上報,要麼一個也不報

固定采樣的配置方式如下圖紅框所示:

Jaeger的用戶端采樣配置(Java版)

要注意的是:根據前置判定(consistent upfront 或者head-based)原則,隻要将上述配置寫入jaeger-service-consumer項目的配置檔案即可,至于jaeger-service-provider維持原狀不做任何改動

執行前面寫的full.sh腳本,編譯建構部署

浏覽器通路http://localhost:18080/hello,産生一些web請求,多通路幾次

看jaeger-service-consumer容器的日志,如下圖,紅框中的sampled=false表示未采樣,三此請求的日志都是如此:

Jaeger的用戶端采樣配置(Java版)

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

Jaeger的用戶端采樣配置(Java版)

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

Jaeger的用戶端采樣配置(Java版)

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

Jaeger的用戶端采樣配置(Java版)

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

Jaeger的用戶端采樣配置(Java版)

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

Jaeger的用戶端采樣配置(Java版)

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

Jaeger的用戶端采樣配置(Java版)

至此,最簡單的固定采樣已完成,來看看更實用的比例采樣

顧名思義,就是按照一定的百分比采樣,配置如下圖所示:

Jaeger的用戶端采樣配置(Java版)

測試比例采樣的方法就是發多個請求,檢查采樣的trace是否是總數的十分之一,我這裡用jmeter來執行多次請求,您可以選擇自己擅長的工具,或者寫代碼寫腳本,甚至手動通路多次

使用jmeter可以控制請求次數,用的是Loop Controller,如下圖紅框所示:

Jaeger的用戶端采樣配置(Java版)

向jaeger-service-consumer的/hello接口發送完一百次請求後,可以從docker容器日志中檢查采樣情況,這裡使用grep和wc指令的組合來統計日志中出現sampled=true和sampled=false的行數,完整的指令如下:

100個請求,采樣率百分之十,但是用上述指令得到的結果并不是精确值10,而是8,再統計未采樣的日志行數(把true改成false),得到的結果是92,總數對得上,但是采樣數并非精确的百分之十,如下圖:

Jaeger的用戶端采樣配置(Java版)

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

Jaeger的用戶端采樣配置(Java版)

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

Jaeger的用戶端采樣配置(Java版)

比例采樣完成了,接下來是限速采樣

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

Jaeger的用戶端采樣配置(Java版)

配置如下圖紅框所示:

Jaeger的用戶端采樣配置(Java版)

咱們的配置是每秒鐘一次采樣,是以驗證的時候要控制好發送請求的時長,我這裡還是用jmeter來發請求的,如下圖紅框所示,jmeter有種Runtime Controller類型的控制器,可以控制持續請求的時長,我這裡設定為10秒:

Jaeger的用戶端采樣配置(Java版)

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

Jaeger的用戶端采樣配置(Java版)

用指令docker logs jaeger-service-consumer| grep 'sampled=true'|wc -l檢視采樣總數,10秒的預期是10個,結果如下,并不精确,隻是接近而已:

Jaeger的用戶端采樣配置(Java版)

清掉所有資料,将時長改成100秒試試,一共發出次852請求:

Jaeger的用戶端采樣配置(Java版)

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

Jaeger的用戶端采樣配置(Java版)

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

Jaeger的用戶端采樣配置(Java版)

還記得《分布式調用鍊跟蹤工具Jaeger?兩分鐘極速體驗》、《Jaeger開發入門(java版)》等文章中的操作嗎?那時咱們并沒有添加任何與采樣有關的配置,但是每次請求都能在Jaeger的web頁面上查到對應的trace,也就是說所有請求全部被采樣了,這是為啥?

如果配置檔案中沒有采樣相關的内容,那麼預設使用的就是遠端配置,具體的資訊就在jaeger的all-in-one容器中,執行下面這個指令,就能看到遠端采樣配置:

上述指令可以看到sampling_strategies.json的内容如下,原來服務端的配置是比例采樣,不過比例是百分之百,這就能解釋為何所有請求都能在Jaeger的web頁面查到trace資訊了:

至此,采樣配置實戰已經完成,希望能給您提供一些參考,輔助您針對實際情況定制更加合适的采樣政策

Java系列

Spring系列

Docker系列

kubernetes系列

資料庫+中間件系列

DevOps系列

微信搜尋「程式員欣宸」,我是欣宸,期待與您一同暢遊Java世界...