聊聊dubbo協議2

本文已收錄 //github.com/lkxiaolou/lkxiaolou 歡迎star。

《聊聊dubbo協議》中介紹了attachments在consumer和provider間的傳遞情況,有個疑問沒有給出答案。

為什麼2.7.x版本的dubbo不支持provider端向consumer端回傳隱式參數呢?今天的續集將揭曉答案。

抓包確定是provider沒發還是consumer丟掉

以下測試基於dubbo 2.7.6版本

在provider端加入下面的代碼

RpcContext.getServerContext().setAttachment("hello", "from_provider");

運行provider,並用consumer不斷地調用,同時進行抓包

sudo tcpdump -i any -vv -A -n port 20880

可以看到provider端將我們的參數回傳了回去,說明是consumer端將數據「弄丟了」

image

分析2.6.x與2.7.x代碼的差別

consumer在收到provider的請求返回時,處理流程如下:

DecodeableRpcResult->decode->case DubboCodec.RESPONSE_VALUE_WITH_ATTACHMENTS->handleAttachment

image

斷點調試能看到,在DecodeableRpcResult中是存在隱式參數的。

看下2.6.x的實現
image

image

RpcResultt的attachments通過filter塞到RpcContext中去,這樣我們就能拿到隱式參數了。

而在2.7.x中,Result的attachments沒有被使用到

image

雖然參數傳了過來,但consumer端沒有將它放入RpcContext中,就沒法使用。

為什麼2.7.x不處理呢?

在2.6.x中,dubbo的請求返回對象只有RpcResult

image

而在2.7.x中,RpcResult沒了,新增了AsyncRpcResult和AppResponse,AppResponse是真實的返回數據,它的attachments是存在隱式參數的,但它會被包裝在AsyncRpcResult中,invoke拿到的是AsyncRpcResult,此時從AppResponse中解出數據時丟了attachments。

image

2.7.x中有一個重要的提升是對異步的支持更加友好,這裡對RpcResult的重構應該就是丟失隱式參數的原因。

dubbo協議如何處理協議的兼容的?

RmiProtocol類中能看到dubbo針對2.7.02.6.3兩個邊界進行了版本兼容
image

版本信息從哪裡來呢?從代碼中看到,從provider的url中獲取參數release(優先)、dubbo來判斷provider的dubbo版本,

dubbo://127.0.0.1:20880/com.newbooo.basic.api.SampleService?anyhost=true&application=ddog-provider&deprecated=false&dubbo=2.0.2&dynamic=true&generic=false&interface=com.newbooo.basic.api.SampleService&methods=getByUid&owner=roshilikang&pid=96150&release=2.7.6&retries=7&side=provider&timestamp=1614235399505

這裏面有些歷史原因,看dubbo 2.6.x的源碼會發現,在2.6.3版本之前,url中dubbo參數代表的是dubbo的版本,而在2.6.3及以後的版本中,dubbo參數代表的是dubbo協議的版本。

image

  • [2.5.3, 2.6.3)版本中,dubbo版本與dubbo協議沒有分開,都是用url上的dubbo參數,值是對應的版本號,取值範圍是 >=2.0.0 && <=2.6.2
  • [2.6.3, 2.7.0)版本,無法從provider註冊的url上看出dubbo版本,dubbo協議版本是從url的dubbo參數獲取,固定為2.0.2
  • 2.7.0之後的版本,dubbo版本在provider的url release參數上,dubbo協議版本在dubbo參數上,目前還是2.0.2

最後

通過這次分析知道了2.7.x的dubbo為什麼provider不能帶回隱式參數了,這應該是個bug。


搜索關注微信公眾號”捉蟲大師”,後端技術分享,架構設計、性能優化、源碼閱讀、問題排查、踩坑實踐。