openEuler結合ebpf提升ServiceMesh服務體驗的探索

語言: CN / TW / HK

服務網格的前世今生

早期的微服務架構上存在着服務發現、負載均衡、授權認證等各種各樣的難題與挑戰。起初微服務踐行者們大多自己實現這麼一套分佈式通信系統來應對這些挑戰,但這無疑造成了業務功能的宂餘,解決此問題的方法就是將共有的分佈式系統通信代碼提取出來設計成一套框架,以框架庫的方式供程序調用。但這個看似完美的方法卻存在着幾個致命的弱點:

  • 框架大部分對業務來説是侵入式修改,需要開發者學習如何使用框架
  • 框架無法做到跨語言使用
  • 處理複雜項目框架庫版本的依賴兼容問題非常棘手,框架庫的升級經常導致業務的被迫升級。

隨着微服務架構的發展,以 Linkeerd/Envoy/NginxMesh 為代表的 sidecar 代理模式應運而生,這就是第一代的 serviceMesh。它作為一個基礎設施層,與業務進程完全解耦,和業務一起部署,接管業務件之間的通信,將網絡數據收發單獨抽象出一層,在這層集中處理了服務發現、負載均衡、授權認證等分佈式系統所需要的功能,實現網絡拓撲中請求的可靠傳輸,較為完美的解決了微服務框架庫中的問題。

但在軟件開發領域沒有萬能的銀彈。ServiceMesh 帶來了這麼多便利的同時,也不可避免的存在着一些問題。傳統方式下,客户端到服務端的消息僅需進出一次內核協議棧即可完成消息傳遞,但在 sidecar 模式中,一般選擇使用內核的 iptables 能力劫持業務流量,這就造成了業務數據需要多次進出內核協議棧,導致業務時延增大,吞吐量變低。

openEuler 21.03 版本下進行 sidecar(envoy)模式基準測試發現,with-envoy 與 non-envoy 模式下,時延有大幅增加

利用 ebpf 能力加速 ServiceMesh

有沒有什麼方法可以在享受 ServiceMesh 提供便利服務的基礎上同時降低並消除網絡時延帶來的影響呢?在這裏就不得不説下 ebpf 技術,ebpf 是在 kernel 中的一項革命性技術,旨在提供不修改內核代碼或加載內核模塊的基礎上更加安全有效的擴展內核的能力。使用 ebpf 能力短接內核網絡協議棧來降低網絡時延,提升 ServiceMesh 的使用體驗,這是目前業界通用的做法。

為了實現短接內核網絡協議棧的目標,我們需要使用到 ebpf 提供的兩種能力,分別是:sockops 與 socket redirection,openEuler 使用的 kernel 版本為 5.10,已經支持了 ebpf 的這兩種能力。

  • sockops 提供了在 tcp socket 創建連接時將 socket 使用 key(一般是四元組)標識後保存在 sockmap 數據結構中的能力
  • socket redirection 在傳輸 tcp 數據時支持使用 key 去 sockmap 中引用 socket,命中後可直接將數據轉發到此 socket 中
  • 對於未在 sockmap 中找到的 socket,正常將數據包通過內核網絡協議棧發送出去

將這些能力結合在一起,就可以在不經過內核網絡協議棧的前提下直接將數據包轉發到對應的 socket 上,完成數據的一次傳輸,降低在內核網絡協議棧上的時間消耗。

在 tcp socket 建立連接的過程中,實際上有兩次連接建立的過程,我們通常稱之為正向連接與反向連接。因正反向連接在建連過程中均需要通過 iptables 信息來獲取實際的 ip 地址與端口號,openEuler 在 iptables 的工作原理上新增 helper 函數,將獲取對端信息的能力下沉到內核中,可以在 ebpf 函數中主動獲取到 iptables 轉換過的地址。這樣我們可以建立一個輔助 map 用於存放正反向連接的對應關係並在 socket redirection 轉發時先從輔助 map 中尋找到對端的連接信息,成功找到對端的連接信息後再進行 socket 轉發動作。原理如下圖

通過 sockops 能力的加速,我們在 openEuler21.03 上實測的結果如下:

  • 測試環境:openEuler-21.03 / 5.10.0-4.17.0.28.oe1.x86_64
  • 組網:fortio-envoy-envoy:80-fortio_server:80
  • qps 提升約為 18%,平均時延提升 15%


下一步的工作:徹底消除 ServiceMesh 性能損耗

從 openEuler21.03 實際測試中可以看出,sockmap 對於 ServiceMesh 可以進行加速,但是加速的結果與不使用 ServiceMesh 相比仍然有較大差距。仔細分析,sockmap 並沒有消耗 socket buff 之間的數據拷貝,也沒有消耗 app/envoy 之間通信時的上下文切換,那問題可能仍然出在 ServiceMesh 架構上。有沒有一種方法,既有 ServiceMesh 易管理、易部署的能力,又能消除其帶來的性能劣化影響?目前 openEuler sig-high-performance-network 正在嘗試這方面的工作,已經有了初步進展。有興趣加入我們一起完成這個目標嗎?可以訂閲以下郵件列表或添加微信聯繫我們~



本文分享自微信公眾號 - openEuler(openEulercommunity)。
如有侵權,請聯繫 [email protected] 刪除。
本文參與“OSC源創計劃”,歡迎正在閲讀的你也加入,一起分享。