天天看點

Dubbo——協定詳解

Dubbo協定詳解

Dubbo協定設計參考了現有TCP/IP協定。一次RPC調用包括協定頭和協定體兩個部分。

16位元組

長的封包頭部主要攜帶了魔法數

(0xdabb)

,以及目前請求封包是否是Request、REsponse、心跳和事件的資訊,請求時也會攜帶目前封包體内序列化協定編号。除此之外還攜帶了請求狀态,以及請求唯一辨別和封包體長度。

Dubbo——協定詳解

Dubbo協定字段解析:

偏移比特位 字段描述 作用
0~7 魔數高位 存儲的是魔法數高位(0xda00)
8~15 魔數低位 存儲的是魔法數低位(0xbb)
16 資料包類型 是否為雙向RPC調用(比如方法調用有傳回值),0為Response,1為Request
17 調用方式

僅在第16位被這設為1的情況下有效

0為單向調用,1位雙向調用

比如在優雅停機時服務端發送readoly不需要雙向調用,這裡标志位就不會設定

18 事件辨別

0為目前資料包是請求或響應包

1為目前資料包是心跳包,比如架構為了保活TCP連接配接,每次用戶端和服務端互相發送心跳包時這個标志位被設定

設定了心跳封包不會透傳到業務方法調用,僅用于架構内部保活機制

19~23 序列化器編号

2為HessianSerializatiion

3為JavaSerialization

4為CompactedJavaSerialization

6為FastJsonSerialization

7為NativJavaSerialization

8為KryoSerialization

9為FstSerialization

24~31 狀态

20為OK

30為CLIENT_TIMEOUT

31為SERVER_TIMEOUT

40為BAD_REQUEST

50為BAD_RESPONSE

32~95 請求編号 這8個位元組存儲RPC請求的唯一id,用來将請求和響應做關聯
96~127 消息體長度 占用的4個位元組存儲消息體長度。在一次RPC請求過程中,消息體中一次會存儲7部分内容

在消息體中,用戶端嚴格按照序列化順序寫入消息,服務端也會遵循相同的順序讀取消息,用戶端發起請求的消息體一次儲存下列内容:Dubbo版本号、服務接口名、服務接口版本、方法名、參數類型、方法參數值和請求額外參數(attachment)。

完整狀态響應碼和作用:

狀态值 狀态符号 作用
20 OK 正确傳回
30 CLIENT_TIMEOUT 用戶端逾時
31 SERVER_TIMEOUT 服務端逾時
40 BAD_REQUEST 請求封包格式錯誤
50 BAD_RESPONSE 響應封包格式錯誤
60 SERVICE_NOT_FOUND 未找到比對的服務
70 SERVICE_ERROR 服務調用錯誤
80 SERVER_ERROR 服務端内部錯誤
90 CLIENT_ERROR 用戶端錯誤
100 SERVER_THREADPOOL_EXHAUSTED_ERROR 服務端線程池滿拒絕執行

Dubbo響應标記:

狀态值 狀态符号 作用
5 RESPONSE_NULL_VALUE_WITH_ATTACHEMENTS 響應空值包含隐藏參數
4 RESPONSE_VALUE_WITH_ATTACHEMENTS 響應結果包含隐藏參數
3 RESPONSE_WITH_EXCEPTION_WITH_ATTACHMENTS 異常傳回包含隐藏參數
2 RESPONSE_NULL_VALUE 響應空值
1 RESPONSE_VALUE 響應結果
RESPONSE_WITH_EXCEPTION 異常傳回

在傳回消息體中,會先把傳回值狀态标記寫入輸入流,根據标記狀态判斷RPC是否正常,比如一次正常RPC調用成功,則先往消息體中寫一個标記1,緊接着再寫方法傳回值。

在網絡通信中(基于TCP)需要解決網絡粘包/解包的問題,一些常用解決辦法比如用回車、換行、固定長度和特殊分隔符等進行處理,通過對前面協定的了解,很容易發現Dubbo其實就是用特殊符号

0xdabb魔數

來分隔處理粘包問題的。

用戶端會使用多線程并發調用服務,Dubbo是如何做到正确響應調用線程的呢?

Dubbo——協定詳解

當用戶端多個線程并發請求時,架構内部會調用Defaultfutre對象的get方法進行等待。在請求發起時,架構内部會建立Request對象,這個時候會被配置設定一個唯一的id,DefaultFuture可以從Request對象中擷取id,并将關聯關系存儲到靜态HashMap中,就是上圖中的Future集合。當用戶端收到響應時,會根據Response對象中的id,從Futures集合中查找對應的DefaultFuture對象,最終會喚醒對應的線程并通知結果。用戶端也會啟動一個定時掃描線程去探測逾時沒有傳回的請求。

繼續閱讀