动态

详情 返回 返回

基於 Coolbpf 的應用可觀測實踐 | 龍蜥技術 - 动态 详情

文/ eBPF 技術探索 SIG

隨着 eBPF 技術的廣泛應用,在操作系統層面提供了更多的觀測能力,站在操作系統層面對應用的行為數據進行 trace 追蹤成了一種應用監控的新手段,本文主要介紹基於 eBPF 實現對應用網絡數據監控的背後邏輯。

一、一個請求數據包的組成

一個完整的應用請求數據包主要包含請求地址信息及具體的請求數據。其中請求地址信息就是我們常説的五元組信息(IP+端口+協議),這部分都是操作系統協議棧負責去解析;而請求數據則由應用通過各種協議去封裝並解析,常見的應用協議有:http、mysql、rediis、dns 等。

應用每一個請求數據的接受與發送都是通過網絡相關的系統調用與操作系統交互,如果請求報文沒有加密,那麼在系統調用處做一個攔截通過函數入參就能輕而易舉的拿到應用協議數據。當下熱門的應用可觀測都是基於此方法對應用網絡數據進行trace,包括:時延、流量統計、協議等。

二、基於系統調用的請求追蹤

2.1 網絡請求模型

一個應用進程基於系統調用的網絡請求模型如下(這裏僅介紹客户端):

  • 通過 socket 去建立套接字,獲得一個 fd 作為 socket 的標識。
  • 通過 connect 填寫 IP 端口信息發起請求連接。
  • 通過read/write請求/接收具體數據,除了read/write系統調用還有send/recvfrom,readv/writev 等可用。
  • 通過 close 結束本次請求。

通過上面的流程圖我們大概瞭解了一次完整網絡請求的系統調用邏輯。有幾點需要注意:

  • 對於單個建鏈完成的請求而言,其發送數據和接收數據往往是串行的,或者説一個 write 必然匹配一個 read,因此我們才能統計到 RT 時間,而 read/write 的返回字節數就可以作為我們的流量統計。
  • write/read 如何配對,對於客户端而言,是先 write 再 read,常用的做法是通過進程 pid 和 socket fd 作為配對標識,實現 write/read 這一次完整請求數據的配對。

2.2 系統調用追蹤

eBPF 技術可以在不改變內核源碼或加載內核模塊情況下在內核插入指定 hook 代碼,能在內核或應用程序執行到一個特定的 hook 點時執行。預定義的 hooks 包含系統調用、 函數出/入口、內核追蹤點、網絡事件等等。

有了 eBPF 做系統調用的 hook 以後,系統調用的事件採集對於我們來説變得格外方便,只不過我們需要注意下哪些事件需要上報及請求數據上報以後的匹配策略。同時對於獲取請求數據是有一些講究,對於 write 發送數據而言在系統調用函數入口直接獲取入參就可以獲取數據,但是對於 read 讀取數據而言我們需要在系統調用函數的出口做 hook 去拿數據。

上文中提到 pid+fd 作為 traceid 作為請求的唯一標誌,有如下兩種方法可以實現:

方法1:當有 connect 的時候先在 BPF map 中記錄下這個 traceid,表示有一個新的請求建立,後續的 read/write 請求數據都是以此為配對。不過在 http 長連接場景下,connect 發起可能在我們 trace 之前,所以只能通過 netlink 等其他方式來獲取鏈接信息。

方法2:實際上我們關心的只是 read/write 的請求數據及如何配對,是否可以僅根據 fd 獲取連接信息?BPF 程序可以拿到當前進程的 task_struct,根據 fd 可以拿到對應的 sock 結構體,sock 結構體中記錄了請求地址信息。

除此之外就是 BPF 框架的技術選型,我們採用了 Coolbpf 開發,通過對 libbpf 的改進,在具備 core 特性的同時提供了更簡潔的 API 接口,exporter 程序可以直接以 so 的形式加載代碼。以上只是網絡請求事件採集的最小單元,藉助 exporter 的其他能力,可以獲得更豐富的數據指標:錯誤數、時延、進程級流量統計等。

三、應用協議識別

在系統調用層面只能識別到 4 層網絡協議,對於應用的 7 層協議無法識別,實際上是在 hook 系統調用拿到 buf 參數後,對 buf 的頭部幾個字節做協議頭解析,目前支持的協議有:http、mysql、kafak、dns、mongo、pgsql、dubbo。對於 https 等加密報文可以通過 uprobe 的方式對 ssl 加密庫做 hook,後續會支持這部分功能。

四、部署

我們在日常值班問題中也有碰到各種網絡抖動時延問題,因此我們將此部分功能放在了 SysOM 智能診斷平台的 agent 中,可以通過容器一鍵部署,並在 grafana 中查看對應的時延分佈及具體的時延請求信息。

同時我們與 sls 合作,也將此部分內核採集的能力輸出給了 iLogtail。

五、what's more

除了上文提到的基於系統調用的應用觀測,對於應用由於自身原因收包緩慢造成網絡“假抖動”的情況,我們基於 Coolbpf 也做了相關觀測實踐。一個完整的收包流程主要分為兩個階段:

階段1:OS 通過軟中斷將數據包上送到應用的收包隊列並通知進程後就算完成了協議棧的收包工作。

階段2:應用得到通知後去收報隊列取包。

這兩個階段可以認為是異步的,我們將數據包到達收包隊列到應用完成取包這段時間作為應用的"收包延遲時間"進行觀測,基於此方法在網絡抖動問題定位中得到了極大幫助。

案例1 某業務應用基於 dubbo 框架容器收到 tcp 包後延遲了將近 1s 業務層才收到

部署 SysOM agent 對“收包延遲時間”進行觀測,發現"收包延遲時間"將近 1 秒,右側紅框部分為時間,單位為納秒,結合左側紅框每次發生延遲時間都在某某時間 42 秒,懷疑跟業務某定時任務相關造成應用自身時延,最終排查到業務有某個任務會定時收集 jvm 的參數,對應用有 stop 動作,停掉該任務後消除了抖動問題。

案例2 業務高峯期,客户端 rpc 耗時比服務端多 20-30ms

業務監控如下:

部署 SysOM agent 對“收包延遲時間”進行觀測,發現對應時間段存在應用“收包延遲時間”較大,因此首先排除了網絡鏈路問題。紅框部分為時間,單位為納秒,圖中時間需要加上 8 小時。

根據時序對比發現是由於此時間段應用在做 GC 導致,最後通過調整 GC 參數解決。

六、總結

以上是基於 Coolbpf 在可觀測性的相關實踐,相關功能都集成在了 SysOM 的 agent 中,後續會引入更多對應用觀測的功能。當應用日誌無法解決問題或者沒有日誌的情況下,利用 eBPF 技術在 OS 層面對應用行為邏輯的觀測,在定位某些應用的疑難問題時有着極大幫助。

參考鏈接:

eBPF 介紹鏈接地址:https://www.rutron.net/posts/...

coolbpf gitee 代碼倉鏈接地址:https://gitee.com/anolis/cool...

內核文檔鏈接地址:https://www.kernel.org/doc/ht...

龍蜥實驗室 coolbpf 鏈接地址:https://lab.openanolis.cn/#/a...

—— 完 ——

Add a new 评论

Some HTML is okay.