Dubbo 協議

功能描述

Dubbo 預設協定使用單一長連線和 NIO 非同步通訊,適用於小數據量、高併發的服務呼叫,以及服務消費端機器數量遠大於服務提供端機器數量的場景。

反之,Dubbo 預設協定不適用於傳輸大數據量的服務,例如檔案傳輸、視訊傳輸等,除非請求量非常低。

dubbo-protocol.jpg

  • 傳輸器:mina、netty、grizzy
  • 序列化:dubbo、hessian2、java、json
  • 調度器:all、direct、message、execution、connection
  • 執行緒池:fixed、cached

預設協定,使用基於 netty 3.2.5.Final 和 hessian2 3.2.1-fixed-2(阿里巴巴嵌入版本) 的 tbremoting 互動。

  • 連線數量:單一連線
  • 連線方式:長連線
  • 傳輸協定:TCP
  • 傳輸方式:NIO 非同步傳輸
  • 序列化:Hessian 二進位序列化
  • 適用範圍:出入參數據包較小(建議小於 100K),消費者數量多於提供者,單一消費者無法壓滿提供者。儘量不要使用 dubbo 協定傳輸大檔案或超大字串。
  • 適用場景:一般的遠端服務方法呼叫

限制

  • 參數和回傳值需要實作 Serializable 介面
  • 參數和回傳值不能自訂實作 ListMapNumberDateCalendar 等介面,只能使用 JDK 自帶的實作,因為 hessian 會做特殊處理,自訂實作的類別中所有屬性值都會遺失。
  • Hessian 序列化,只傳遞成員屬性值和值類型,不傳遞方法或靜態變數,相容性**由吳亞軍提供**
資料通訊情況結果
A->BA 類別多了一個屬性(或 B 類別少了一個屬性)沒有拋出異常,屬性值較多的 A,B 沒有的屬性值不會處理,其他正常
A->B列舉 A 比 B 多一個列舉值(或 B 比 A 少一個列舉值)A 使用額外的列舉值進行傳輸
A->B列舉 A 比 B 多一個列舉值(或 B 比 A 少一個列舉值)A 不使用額外的列舉值進行傳輸
A->BA 和 B 的屬性名稱相同,但類型不同拋出異常
A->BserialId 不同正常傳輸

介面新增方法對客戶端沒有影響,如果客戶端不需要此方法,客戶端無需重新部署。輸入參數和結果集中新增屬性對客戶端沒有影響,如果客戶端不需要新的屬性,無需重新部署。

輸入參數和結果集屬性名稱的變更對客戶端序列化沒有影響,但是如果客戶端沒有重新部署,無論輸入還是輸出,屬性名稱變更的屬性值都取不到。

總結

  • 伺服器端和客戶端並不需要領域物件完全一致,而是遵循最大匹配原則。
  • 會拋出異常的情況:列舉值多一種少一種,恰好使用不同的,或者屬性名稱相同,但類型不同。

使用場景

適用於併發量大、數據量小的服務呼叫,且服務消費者遠大於服務提供者。

使用方法

配置協議

<dubbo:protocol name="dubbo" port="20880" />

設定預設協議

<dubbo:provider protocol="dubbo" />

設定某個服務的協議

<dubbo:service interface="..." protocol="dubbo" />

多埠

<dubbo:protocol id="dubbo1" name="dubbo" port="20880" />
<dubbo:protocol id="dubbo2" name="dubbo" port="20881" />

配置協議選項

<dubbo:protocol name="dubbo" port="9090" server="netty" client="netty" codec="dubbo" serialization="hessian2" charset="UTF-8" threadpool="fixed" threads="100 " queues="0" iothreads="9" buffer="8192" accepts="1000" payload="8388608" />

多連線配置

預設情況下,Dubbo 協議每個服務、每個提供者、每個消費者使用單一長連線。如果數據量較大,可以使用多連線。

<dubbo:service interface="..." connections="1"/>
<dubbo:reference interface="..." connections="1"/>
  • <dubbo:service connections="0"><dubbo:reference connections="0"> 表示該服務使用 JVM 共享持久連線。預設值
  • <dubbo:service connections="1"><dubbo:reference connections="1"> 表示該服務使用獨立持久連線。
  • <dubbo:service connections="2"><dubbo:reference connections="2"> 表示該服務使用兩個獨立持久連線。

為防止被大量的連線撐爆,可在服務提供方限制接收連線的最大個數,以達到服務提供方自我保護的目的。

<dubbo:protocol name="dubbo" accepts="1000" />

常見問題

Q1

為什麼消費者要比提供者多?

因為 dubbo 協議使用單一長連線,假設網路是千兆網卡 1024Mbit=128MByte,根據測試經驗數據,每個連線最多只能跑到 7MByte(不同環境可能不一樣,僅供參考),理論上 1 個服務提供者需要 20 個服務消費者才能把網卡跑滿。

Q2

為什麼不能傳大包?

因為 dubbo 協議使用單一長連線,如果每次請求的數據包大小為 500KByte,假設網路是千兆網卡 1024Mbit=128MByte,每個連線最多只能跑到 7MByte(不同環境可能不一樣),單個服務提供者的最大 TPS(每秒事務數)為:128MByte / 500KByte = 262。單個消費者調用單個服務提供者的最大 TPS(每秒事務數)為:7MByte / 500KByte = 14。如果可以接受,可以考慮使用,否則網路將成為瓶頸。

Q3

為什麼使用非同步單一長連線?

由於目前服務的現況是服務提供者少,通常只有幾台機器,但服務消費者多,整個網站都可能在訪問該服務。例如,Morgan 的提供者只有 6 台,但消費者卻有數百個。或者,每天有 1.5 億次呼叫。如果使用傳統的 Hessian 服務,服務提供者很容易不堪重負。透過單一連線,可以保證單個消費者不會壓垮提供者,長期連線,減少連線握手驗證等。並使用非同步 IO,重複使用執行緒池,防止 C10K 問題。


上次修改時間:2023 年 1 月 2 日:增強英文文件 (#1798) (95a9f4f6c1c)