Jaeger的客戶端取樣配置(Java版)

程式設計師欣宸發表於2021-12-21

歡迎訪問我的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的應用)配置取樣,並且動手驗證效果,常用的客戶端取樣策略有以下三種:
  1. 固定:要麼全部取樣,要門全部不取樣
  2. 比例:按照指定比例取樣
  3. 限速:固定時間週期內取樣固定數量,例如每秒一個
  • 接下來,逐個配置和體驗這三種取樣的效果

關於實戰用的工程

  • 取樣配置實戰不涉及編碼,只需要改一些配置,所以沒必要大張旗鼓的新建工程寫程式碼,用《Jaeger開發入門(java版)》一文中的兩個maven子工程即可:服務提供方<font color="blue">jaeger-service-provider</font>和服務呼叫方<font color="blue">jaeger-service-consumer</font>,都做成docker映象,用docker-compose啟動,網路架構如下圖:

在這裡插入圖片描述

  • 請確保專案的日誌模板中已新增了<font color="blue">traceId</font>、<font color="blue">spanId</font>、<font color="blue">sampled</font>等變數,如下圖紅框所示,有了這些配置,我們們在日誌中就能看到對應的trace是否被取樣(這一步<font color="red">非常重要</font>):

在這裡插入圖片描述

  • 為了方便修改程式碼後重新部署啟動,我寫了個名為<font color="blue">full.sh</font>的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)原則,只要將上述配置寫入<font color="blue">jaeger-service-consumer</font>專案的配置檔案即可,至於<font color="blue">jaeger-service-provider</font>維持原狀不做任何改動
  • 執行前面寫的full.sh指令碼,編譯構建部署
  • 瀏覽器訪問<font color="blue">http://localhost:18080/hello</font>,產生一些web請求,多訪問幾次
  • 看jaeger-service-consumer容器的日誌,如下圖,紅框中的<font color="red">sampled=false</font>表示未取樣,三此請求的日誌都是如此:

在這裡插入圖片描述

  • 再看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全部上報:

在這裡插入圖片描述

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

比例取樣

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

在這裡插入圖片描述

  • 執行前面寫的<font color="blue">full.sh</font>指令碼,編譯構建部署
  • 測試比例取樣的方法就是發多個請求,檢查取樣的trace是否是總數的十分之一,我這裡用jmeter來執行多次請求,您可以選擇自己擅長的工具,或者寫程式碼寫指令碼,甚至手動訪問多次
  • 使用jmeter可以控制請求次數,用的是<font color="blue">Loop Controller</font>,如下圖紅框所示:

在這裡插入圖片描述

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

在這裡插入圖片描述

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

在這裡插入圖片描述

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

在這裡插入圖片描述

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

限速取樣

  • 關於限速,似乎不夠具體不便於理解,但是看看官方文件上的關鍵字<font color="blue">leaky bucket</font>,如下圖紅框,聰明的您一定想到了其中的關鍵,漏桶限流演算法(注意,是漏桶,不是令牌桶,漏桶演算法的峰值和桶大小有關):

在這裡插入圖片描述

  • 配置如下圖紅框所示:

在這裡插入圖片描述

  • 執行前面寫的<font color="blue">full.sh</font>指令碼,編譯構建部署
  • 我們們的配置是每秒鐘一次取樣,所以驗證的時候要控制好傳送請求的時長,我這裡還是用jmeter來發請求的,如下圖紅框所示,jmeter有種<font color="blue">Runtime Controller</font>型別的控制器,可以控制持續請求的時長,我這裡設定為10秒:

在這裡插入圖片描述

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

在這裡插入圖片描述

  • 用命令<font color="blue">docker logs jaeger-service-consumer| grep 'sampled=true'|wc -l</font>檢視取樣總數,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
  }
}
  • 至此,取樣配置實戰已經完成,希望能給您提供一些參考,輔助您針對實際情況定製更加合適的取樣策略

你不孤單,欣宸原創一路相伴

  1. Java系列
  2. Spring系列
  3. Docker系列
  4. kubernetes系列
  5. 資料庫+中介軟體系列
  6. DevOps系列

歡迎關注公眾號:程式設計師欣宸

微信搜尋「程式設計師欣宸」,我是欣宸,期待與您一同暢遊Java世界...
https://github.com/zq2599/blog_demos

相關文章