作者:顧欣
Triple 是 Dubbo 3 提出的基于 HTTP2 的開放協議,旨在解決 Dubbo 2 私有協議帶來的互通性問題,Triple 基于 HTTP/2 定制自己的流控,支持通過特定的例外通知客戶端業務層服務端負載高情況,保護了服務端被大流量擊垮,提高系統高可用能力,
一、流控反壓現狀
客戶端和服務器端在接收資料的時候有一個緩沖區來臨時存盤資料,但是緩沖區的大小是有限制的,所以有可能會出現緩沖區溢位的情況,HTTP 通過流控保護資料溢位丟失風險,
1、HTTP/1 流控
在 HTTP/1.1 中,流量的控制依賴的是底層TCP協議,在客戶端和服務器端建立連接的時候,會使用系統默認的設定來建立緩沖區,在資料進行通信的時候,會告訴對方它的接收視窗的大小,這個接收視窗就是緩沖區中剩余的可用空間,如果接收視窗大小為零,則說明接收方緩沖區已滿,則發送方將不再發送資料,直到客戶端清除其內部緩沖區,然后請求恢復資料傳輸,
2、HTTP/2 流控
HTTP/2 使用了多路復用機制,一個TCP連接可以有多個 HTTP/2 連接,故在 HTTP/2 中,有更加精細的流控制機制,允許服務端實作自己資料流和連接級的流控制,服務端與客戶端初次見了連接時,會通過發送 HTTP/2 SettingsFrame設定初始化的流控視窗大小,用于 Stream 級別流控,默認為 65,535 位元組,定好流控視窗后,每次客戶端發送資料就會減少流控視窗的大小,服務端收到資料后會發送視窗更新包(WINDOW_UPDATE frame)通知客戶端更新視窗,客戶端收到視窗更新包后就會增加對應值的流控視窗,從而達到動態控制的目的,

二、Triple流控反壓
Netty 基于 HTTP/2 實作了基礎的流控,當服務端負載過高,客戶端發送視窗為 0 時,新增請求就無法被發送出去,會在快取到客戶端待發送請求佇列中,快取資料過大,就會造成客戶端記憶體溢位,影響業務程式,
Triple 基于 Netty 實作了 HTTP/2 協議,通過 HTTP/2 FlowController介面統一封裝,在實作分為進站(inbound)和出站(outbound)兩個維度的實作,Triple 在 inbound 流量上使用了 Netty 的默認流控實作,在 outbound 上實作了自己流控,基于服務端負載,將服務端流量壓力透傳到客戶端業務層,實作客戶端的業務反壓,暫停業務繼續發送請求,保護服務端不被大流量擊垮,
1、連接初始化
Triple在初次建立連接時,通過 TripleHttpProtocol 初始化 HTTP/2 配置,默認流控視窗 DEFAULT_WINDOW_INIT_SIZE = MIB_8,并在服務端和客戶端加入自己的 outbound 流控介面,

2、Inbound流控
Inbound 流量會通過 DefaultHttpLocalFlowController 的 consumeBytes 方法實作流控視窗更新與發送,
1) 入口傳入HTTP 流與更新資料大小

2) 找到對應連接實作資料消費

3) 更新流控視窗

4) 發送流控更新資料包(window_update)

3、Outbound流控
Outbound 通過 Triple 自己的流控實作 TriHttpRemoteFlowController,將服務端壓力反饋到業務層,保護服務端被大流量擊垮,
1) 發送資料時判斷是否還有視窗

2) 視窗為0時拋出特定例外

3) 反饋客戶端流控例外

4、總結
Triple 通過將底層客戶端發送視窗為 0 場景封裝為特定流控例外,透傳至客戶端上層業務,阻止客戶端業務繼續資料發送,有效的保護了服務端被大流量擊垮和客戶端的記憶體溢位的問題,
三、未來展望
目前 Triple 已經基本實作了流控反壓能力,未來我們將深度聯動業務,基于業務負載自適應調整反壓流控,一是在 inbound 上將流控視窗包發送時機調整到服務端業務處理完成后,二是在 outbound 流量上關聯客戶端業務層,動態調整客戶端發送速率,從而實作基于服務端業務負載動態反壓流控機制,
歡迎在 https://github.com/apache/dubbo 給 Dubbo Star,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/540975.html
標籤:其他
上一篇:docker高級篇-docker-compose容器編排介紹及實戰
下一篇:一、對稱加密(DES加密)
