MOSN 原始碼解析 - 連線池

rootsongjc發表於2020-04-07

本文的內容基於 MOSN v0.10.0. 作者:子懿(阿里雲)

在連線管理中我們主要介紹 MOSN 實現連線池的功能,連線池是上下游 MOSN 之間進行長連線複用以提高轉發效率與降低時延的關鍵,MOSN 連線池提供基於 HTTP1, HTTP2, SOFARPC, XProtocol 協議的連線池。

而 “健康檢查” 是一種實時檢測上游伺服器是否正確提供服務的機制,一般分為 “主動健康檢查” 和 “被動健康檢查”。主動健康檢查由健康檢查模組主動發起,通過週期性的傳送健康檢查資料包對伺服器進行健康檢查;被動健康檢查則是在轉發業務資料包文時發現上游伺服器無法正確的提供服務,而被動摘除的手段。

MOSN 當前只支援主動健康檢查,支援的協議包括 SOFARPC 以及 HTTP2,它是 Cluster 的一個模組,可通過配置決定是否開啟對 Cluster 中的 Host 進行健康檢查,以及配置健康檢查時使用的引數。

通過主動健康檢查,MOSN 可以及時摘除不健康的機器,從而為連線管理提供有效的 Upstream,提高建連的成功率。同時基於健康檢查模組還可以做連線的保活,從而維持長連線。

MOSN 連線管理

HTTP/1.0 預設使用短連線,即客戶端和伺服器每進行一次 HTTP 操作建立一次連線,任務結束中斷連線。HTTP/1.1 起預設使用長連線用以保持連線特性。使用長連線的 HTTP 協議需在響應頭新增 Connection:keep-alive。HTTP/1 雖然能夠維持長連線,但是單條連線同一時間只能處理一個請求/相應,意味著如果同時收到 4 個請求需要建立 4 條 TCP 連線,連線的成本相對來說比較高昂;HTTP/2 引入 Stream/Frame 的概念,支援分幀多路複用能力,在邏輯上區分出成對的請求 Stream 和響應 Stream,從而單條連線併發處理多個請求/響應,解決 HTTP/1 連線數與併發數成正比的問題。

HTTP/1.1 不支援多路複用,使用經典的 Ping-Pong 模式:在請求傳送之後必須獨佔當前連線等待伺服器端給出這個請求的應答然後才能釋放連線。因此 HTTP/1.1 下併發多個請求就必須採用多連線,為了提升效能通常使用長連線 + 連線池的設計。MOSN 長連線多路複用處理流程:

  • MOSN 從 downstream 接收一個請求 request,依據報文擴充套件多路複用介面 GetRequestId 獲取到請求在這條連線上的身份標識並且記錄到關聯對映中待用;
  • 請求經過 MOSN 的路由、負載均衡處理,選擇一個 upstream,同時在這條連線上新建一個請求流,並呼叫文擴充套件多路複用介面 SetRequestId 封裝新的身份標識,並記錄到關聯對映中與 downstream 資訊組合;
  • MOSN 從 upstream 接收一個響應 response,依據報文擴充套件多路複用介面 GetRequestId 獲取到請求在這條連線上的身份標識。此時可以從上下游關聯對映表中,根據 upstream 資訊找到對應的 downstream 資訊;
  • 依據 downstream request 的資訊,呼叫文擴充套件多路複用介面 SetRequestId 設定響應的 requestId,並回復給 downstream。

MOSN 在 Proxy 下游 Request 時,會根據 Upstream Host 地址以及與 Upstream Host 的應用層協議獲取對應的長連線,之後在長連線上封裝對應協議的 Stream, 並轉發資料,從而避免每次與 Upstream 新建連線帶來的握手開銷以提高轉發效能、降低時延。在建立 Stream 的時候,連線池還提供熔斷保護功能,將 Stream 建立的數量約束在一個閾值以下。當前 MOSN 支援的連線池包括:SOFARPC、HTTP1、HTTP2、XProocol 等應用層協議的連線池.

  • MOSN 的 Proxy 模組在 Downstream 收到 Request 的時候,在經過路由、負載均衡等模組處理獲取到 Upstream Host 以及對應的轉發協議時,會去 Cluster Manager 獲取連線池 ,如果連線池不存在則建立並加入快取,之後在長連線上建立 Stream,併傳送資料。

如下圖所示為連線池工作的示意圖:

img

1. 介面描述

  • 連線池介面
    • Protocol() 用於返回當前連線池對應的協議;
    • NewStream() 用於在當前連線池上建立 Stream;
    • Close() 用於關閉長連線中的 TCP 套接字。

img

  • 連線池事件監聽的介面
    • OnFailure 用於建立 Stream 失敗時的回撥,用於 reset stream 相關工作;
    • OnReady 是連線池準備就緒,Stream 建立成功時的回撥,用於 Stream 傳送資料。

img

2.資料結構

  • ConnNewPoolFactories 為不同協議建立對應連線池的工廠類,HTTP1、SOFARPC、 HTTP2、XProtocol 等協議分別呼叫註冊函式 RegisterNewPoolFactory ,註冊自己的建立方法。
  • clusterManager 中的 protocolConnPool 為全域性連線池的實現,其型別為二級 sync.Map,其中第一級 Map 的 key 為協議型別,第二級 Map 的 key 為 Host 地址,value 為 ConnectionPool
  • upstreamRequest 中維護 connPoolconnPool 的使用者,用來建立連線。

3.連線池使用

初始化連線池

  • clusterManager 在查詢本地連線池時,如果對應協議和 Host 的連線池不存在,則呼叫對應協議的工廠方法建立連線池,如果存在的話,則直接返回連線池。

img

獲取連線池

  • downstream 在收到下游的 request 並往上游轉發時,會根據協議和挑選的 upstream 地址選擇連線池並賦值給 upstreamconnPool

img

使用連線池

  • upstreamRequest 在往上游轉發資料時,會呼叫 connPool 對應的 Newstream 方法封裝 stream 併傳送。

img

MOSN 健康檢查

MOSN 的健康檢查是一種主動健康檢查機制,他是 Cluster 內在的一個模組。當前支援的健康檢查功能包括:

  1. 健康檢查支援可配置,配置包括健康檢查使用的協議、健康檢查報文傳送間隔、超時時間、更新閾值等;
  2. 提供健康檢查介面,允許不同健康檢查協議的擴充套件;
  3. 提供基於健康檢查結果的 callback 機制,允許自定義對健康檢查結果的處理方式;
  4. 基於週期性的健康檢查,可實現心跳機制,用於長連線的保活。

如下為當前健康檢查工作的示意圖:

img

Cluster 的 HealthChecker 模組在開啟的情況下,會根據配置的協議建立基於 SOFARPC, HTTP2 或者其他協議的健康檢查;健康檢查模組會與 Cluster 中的所有 Host - 建立 HealthCheckSession,在 Session 上週期性傳送健康檢查報文,並開啟定時器,如果 Response 在規定時間內未達/到達則判斷健康檢查失敗/成功,健康檢查失敗/成功次數到一定閾值後 Callback 模組會更新機器的健康狀態。

1.健康檢查配置

對 Cluster 的健康檢查支援的配置包括: * 發起健康檢查的應用層協議,如果子協議存在,還支援配子協議 * 健康檢查報文的超時時間 * 發起健康檢查報文的間隔 * 更新 Host 狀態的閾值 * 健康檢查的路徑和對應的 Service 資訊

img

2.介面描述

  • HealthChecker 介面用來控制對整個 Cluster 進行健康檢查,其中:
    • Start/Stop 開啟/關閉 對 Cluster 的健康檢查,會開啟 Host 的健康檢查 Session;
    • AddHostCheckCompleteCb 用來設定對健康檢查結果的回撥,關於 cb 的定義在下面會介紹;
    • OnClusterMemberUpdate 是在外部 Cluster 的 Hosts 發生變化時,例如主機上下線等,來更新健康檢查的範圍。

img

  • HealthCheckCb 是基於健康檢查結果對 Host 狀態進行更新的回撥函式,發生在健康檢查的結果對 Host 的狀態產生影響之後,如果健康檢查失敗,則會將 Host 置為 Unhealty,否則置為 Healthy。

img

  • HealthCheckSession 是健康檢查模組與每個 Host 建立的用於健康檢查的 session,在這個 session 上可以傳送健康檢查資料包並處理 response。
    • Start/Stop 開啟/停止 對 Host 的健康檢查;
    • SetUnhealthy 為健康檢查失敗達到一定閾值之後將 Host 的狀態設定為 Unhealthy。

img

3.資料結構

  • Cluster 中的 healthChecker 在 Cluster 建立的時候基於配置進行初始化,如果配置支援健康檢查,則開啟。
  • healthChecker 是實現 Cluster 健康檢查的類,其中包含對所有的 Host 的進行健康檢查的 healthCheckSessions。在實現基於不同的協議的健康檢查時,會繼承這個類,並重寫一些方法。
  • healthCheckSesion 是對 Host 健康檢查的 session,其中包含兩個定時器,以及對應的健康狀態更新閾值。在實現基於不同的協議的健康檢查時,會繼承這個類,並重寫一些方法。

4.工作流程

下圖是健康檢查的工作時序圖,包括 從 Cluster 建立健康檢查器開始,到對每個 Host 建立健康檢查的 Session,到對 Host 傳送健康檢查資料包,到處理 Host 的響應,到更新 Host 的狀態。

img

總結

本文根據 MOSN 的原始碼分析 MOSN 對連線池的設計與實現,其基於 upstreamRequest 往上游轉發資料呼叫 connPool 對應的 Newstream 方法傳送 Stream。


參考資料:

原文地址:https://mosn.io/zh/blog/code/mosn-connection-pool/

更多原創文章乾貨分享,請關注公眾號
  • MOSN 原始碼解析 - 連線池
  • 加微信實戰群請加微信(註明:實戰群):gocnio

相關文章