Dubbo 協議
功能描述
Dubbo 預設協定使用單一長連線和 NIO 非同步通訊,適用於小數據量、高併發的服務呼叫,以及服務消費端機器數量遠大於服務提供端機器數量的場景。
反之,Dubbo 預設協定不適用於傳輸大數據量的服務,例如檔案傳輸、視訊傳輸等,除非請求量非常低。
- 傳輸器: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
介面 - 參數和回傳值不能自訂實作
List
、Map
、Number
、Date
、Calendar
等介面,只能使用 JDK 自帶的實作,因為 hessian 會做特殊處理,自訂實作的類別中所有屬性值都會遺失。 - Hessian 序列化,只傳遞成員屬性值和值類型,不傳遞方法或靜態變數,相容性**由吳亞軍提供**
資料通訊 | 情況 | 結果 |
---|---|---|
A->B | A 類別多了一個屬性(或 B 類別少了一個屬性) | 沒有拋出異常,屬性值較多的 A,B 沒有的屬性值不會處理,其他正常 |
A->B | 列舉 A 比 B 多一個列舉值(或 B 比 A 少一個列舉值) | A 使用額外的列舉值進行傳輸 |
A->B | 列舉 A 比 B 多一個列舉值(或 B 比 A 少一個列舉值) | A 不使用額外的列舉值進行傳輸 |
A->B | A 和 B 的屬性名稱相同,但類型不同 | 拋出異常 |
A->B | serialId 不同 | 正常傳輸 |
介面新增方法對客戶端沒有影響,如果客戶端不需要此方法,客戶端無需重新部署。輸入參數和結果集中新增屬性對客戶端沒有影響,如果客戶端不需要新的屬性,無需重新部署。
輸入參數和結果集屬性名稱的變更對客戶端序列化沒有影響,但是如果客戶端沒有重新部署,無論輸入還是輸出,屬性名稱變更的屬性值都取不到。
總結
- 伺服器端和客戶端並不需要領域物件完全一致,而是遵循最大匹配原則。
- 會拋出異常的情況:列舉值多一種少一種,恰好使用不同的,或者屬性名稱相同,但類型不同。
使用場景
適用於併發量大、數據量小的服務呼叫,且服務消費者遠大於服務提供者。
使用方法
配置協議
<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 問題。