本文已收錄 https://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端將資料“弄丟了”
分析2.6.x與2.7.x程式碼的差別
consumer在收到provider的請求返回時,處理流程如下:
DecodeableRpcResult
->decode
->case DubboCodec.RESPONSE_VALUE_WITH_ATTACHMENTS->handleAttachment
斷點除錯能看到,在DecodeableRpcResult
中是存在隱式引數的。
看下2.6.x的實現
RpcResultt的attachments通過filter塞到RpcContext中去,這樣我們就能拿到隱式引數了。
而在2.7.x中,Result的attachments沒有被使用到
雖然引數傳了過來,但consumer端沒有將它放入RpcContext中,就沒法使用。
為什麼2.7.x不處理呢?
在2.6.x中,dubbo的請求返回物件只有RpcResult
而在2.7.x中,RpcResult沒了,新增了AsyncRpcResult和AppResponse,AppResponse是真實的返回資料,它的attachments是存在隱式引數的,但它會被包裝在AsyncRpcResult中,invoke拿到的是AsyncRpcResult,此時從AppResponse中解出資料時丟了attachments。
2.7.x中有一個重要的提升是對非同步的支援更加友好,這裡對RpcResult的重構應該就是丟失隱式引數的原因。
dubbo協議如何處理協議的相容的?
從RmiProtocol
類中能看到dubbo針對2.7.0
、2.6.3
兩個邊界進行了版本相容
版本資訊從哪裡來呢?從程式碼中看到,從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×tamp=1614235399505
這裡面有些歷史原因,看dubbo 2.6.x的原始碼會發現,在2.6.3版本之前,url中dubbo引數代表的是dubbo的版本,而在2.6.3及以後的版本中,dubbo引數代表的是dubbo協議的版本。
[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。
搜尋關注微信公眾號"捉蟲大師",後端技術分享,架構設計、效能優化、原始碼閱讀、問題排查、踩坑實踐。