MOSN 原始碼解析 - 連線池
本文的內容基於 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,併傳送資料。
如下圖所示為連線池工作的示意圖:
1. 介面描述
- 連線池介面
-
Protocol()
用於返回當前連線池對應的協議; -
NewStream()
用於在當前連線池上建立 Stream; -
Close()
用於關閉長連線中的 TCP 套接字。
-
- 連線池事件監聽的介面
-
OnFailure
用於建立 Stream 失敗時的回撥,用於 reset stream 相關工作; -
OnReady
是連線池準備就緒,Stream 建立成功時的回撥,用於 Stream 傳送資料。
-
2.資料結構
-
ConnNewPoolFactories
為不同協議建立對應連線池的工廠類,HTTP1、SOFARPC、 HTTP2、XProtocol 等協議分別呼叫註冊函式RegisterNewPoolFactory
,註冊自己的建立方法。 - 類
clusterManager
中的protocolConnPool
為全域性連線池的實現,其型別為二級sync.Map
,其中第一級 Map 的 key 為協議型別,第二級 Map 的 key 為 Host 地址,value 為ConnectionPool
。 - 類
upstreamRequest
中維護connPool
是connPool
的使用者,用來建立連線。
3.連線池使用
初始化連線池
-
clusterManager
在查詢本地連線池時,如果對應協議和 Host 的連線池不存在,則呼叫對應協議的工廠方法建立連線池,如果存在的話,則直接返回連線池。
獲取連線池
-
downstream
在收到下游的 request 並往上游轉發時,會根據協議和挑選的upstream
地址選擇連線池並賦值給upstream
的connPool
。
使用連線池
-
upstreamRequest
在往上游轉發資料時,會呼叫connPool
對應的Newstream
方法封裝 stream 併傳送。
MOSN 健康檢查
MOSN 的健康檢查是一種主動健康檢查機制,他是 Cluster 內在的一個模組。當前支援的健康檢查功能包括:
- 健康檢查支援可配置,配置包括健康檢查使用的協議、健康檢查報文傳送間隔、超時時間、更新閾值等;
- 提供健康檢查介面,允許不同健康檢查協議的擴充套件;
- 提供基於健康檢查結果的 callback 機制,允許自定義對健康檢查結果的處理方式;
- 基於週期性的健康檢查,可實現心跳機制,用於長連線的保活。
如下為當前健康檢查工作的示意圖:
Cluster 的 HealthChecker
模組在開啟的情況下,會根據配置的協議建立基於 SOFARPC, HTTP2 或者其他協議的健康檢查;健康檢查模組會與 Cluster 中的所有 Host - 建立 HealthCheckSession
,在 Session
上週期性傳送健康檢查報文,並開啟定時器,如果 Response 在規定時間內未達/到達則判斷健康檢查失敗/成功,健康檢查失敗/成功次數到一定閾值後 Callback 模組會更新機器的健康狀態。
1.健康檢查配置
對 Cluster 的健康檢查支援的配置包括: * 發起健康檢查的應用層協議,如果子協議存在,還支援配子協議 * 健康檢查報文的超時時間 * 發起健康檢查報文的間隔 * 更新 Host 狀態的閾值 * 健康檢查的路徑和對應的 Service 資訊
2.介面描述
-
HealthChecker
介面用來控制對整個 Cluster 進行健康檢查,其中:- Start/Stop 開啟/關閉 對 Cluster 的健康檢查,會開啟 Host 的健康檢查 Session;
-
AddHostCheckCompleteCb
用來設定對健康檢查結果的回撥,關於 cb 的定義在下面會介紹; -
OnClusterMemberUpdate
是在外部 Cluster 的 Hosts 發生變化時,例如主機上下線等,來更新健康檢查的範圍。
-
HealthCheckCb
是基於健康檢查結果對 Host 狀態進行更新的回撥函式,發生在健康檢查的結果對 Host 的狀態產生影響之後,如果健康檢查失敗,則會將 Host 置為 Unhealty,否則置為 Healthy。
-
HealthCheckSession
是健康檢查模組與每個 Host 建立的用於健康檢查的 session,在這個 session 上可以傳送健康檢查資料包並處理 response。- Start/Stop 開啟/停止 對 Host 的健康檢查;
- SetUnhealthy 為健康檢查失敗達到一定閾值之後將 Host 的狀態設定為 Unhealthy。
3.資料結構
- Cluster 中的
healthChecker
在 Cluster 建立的時候基於配置進行初始化,如果配置支援健康檢查,則開啟。 -
healthChecker
是實現 Cluster 健康檢查的類,其中包含對所有的 Host 的進行健康檢查的healthCheckSessions
。在實現基於不同的協議的健康檢查時,會繼承這個類,並重寫一些方法。 -
healthCheckSesion
是對 Host 健康檢查的 session,其中包含兩個定時器,以及對應的健康狀態更新閾值。在實現基於不同的協議的健康檢查時,會繼承這個類,並重寫一些方法。
4.工作流程
下圖是健康檢查的工作時序圖,包括 從 Cluster 建立健康檢查器開始,到對每個 Host 建立健康檢查的 Session,到對 Host 傳送健康檢查資料包,到處理 Host 的響應,到更新 Host 的狀態。
總結
本文根據 MOSN 的原始碼分析 MOSN 對連線池的設計與實現,其基於 upstreamRequest
往上游轉發資料呼叫 connPool
對應的 Newstream
方法傳送 Stream。
參考資料:
原文地址:https://mosn.io/zh/blog/code/mosn-connection-pool/
- 加微信實戰群請加微信(註明:實戰群):gocnio
相關文章
- 資料庫連線池-Druid資料庫連線池原始碼解析資料庫UI原始碼
- OkHttp3原始碼解析(三)——連線池複用HTTP原始碼
- SOFA-MOSN原始碼解析—配置詳解原始碼
- Hikari連線池原始碼解讀原始碼
- ServiceStack.Redis的原始碼分析(連線與連線池)Redis原始碼
- 《四 資料庫連線池原始碼》手寫資料庫連線池資料庫原始碼
- 以太坊交易池原始碼解析原始碼
- netty原始碼分析之新連線接入全解析Netty原始碼
- 從原始碼分析DBCP資料庫連線池的原理原始碼資料庫
- 雲原生網路代理 MOSN 開源社群發起原始碼解析活動原始碼
- 連線池
- Java原始碼解析 ThreadPoolExecutor 執行緒池Java原始碼thread執行緒
- Java原始碼解析 - ThreadPoolExecutor 執行緒池Java原始碼thread執行緒
- Java執行緒池ThreadPoolExecutor原始碼解析Java執行緒thread原始碼
- 雨露均沾的OkHttp—WebSocket長連線的使用&原始碼解析HTTPWeb原始碼
- Netty原始碼解析 -- 記憶體池與PoolArenaNetty原始碼記憶體
- HTTP連線池HTTP
- django連線池Django
- 在SpringBoot中使用R2DBC連線池的原始碼和教程Spring Boot原始碼
- 【Mybatis原始碼解析】- JDBC連線資料庫的原理和操作MyBatis原始碼JDBC資料庫
- MQTT(EMQX) - SpringBoot 整合MQTT 連線池 Demo - 附原始碼 + 線上客服聊天架構圖MQQTSpring Boot原始碼架構
- MongoDB原始碼分析之連結池(ConnPool)GWMongoDB原始碼
- Http持久連線與HttpClient連線池HTTPclient
- 連線池和連線數詳解
- 從原始碼中分析關於phpredis中的連線池可持有數目原始碼PHPRedis
- btcpool礦池原始碼分析(3)-BlockMaker模組解析TCP原始碼BloC
- btcpool礦池原始碼分析(4)-GbtMaker模組解析TCP原始碼
- btcpool礦池原始碼分析(5)-JobMaker模組解析TCP原始碼
- btcpool礦池原始碼分析(6)-nmcauxmaker模組解析TCP原始碼UX
- btcpool礦池原始碼分析(6)-PoolWatcher模組解析TCP原始碼
- btcpool礦池原始碼分析(7)-sharelogger模組解析TCP原始碼
- btcpool礦池原始碼分析(9)-statshttpd模組解析TCP原始碼httpd
- btcpool礦池原始碼分析(10)-StratumServer模組解析TCP原始碼Server
- 執行緒池執行模型原始碼全解析執行緒模型原始碼
- 自定義連線池
- ElasticSearch連線池建立Elasticsearch
- MOSN 擴充套件機制解析套件
- Netty原始碼解析一——執行緒池模型之執行緒池NioEventLoopGroupNetty原始碼執行緒模型OOP