本文已收錄 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.22.7.0之后的版本,dubbo版本在provider的url release引數上,dubbo協議版本在dubbo引數上,目前還是2.0.2
最后
通過這次分析知道了2.7.x的dubbo為什么provider不能帶回隱式引數了,這應該是個bug,
搜索關注微信公眾號"捉蟲大師",后端技術分享,架構設計、性能優化、原始碼閱讀、問題排查、踩坑實踐,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/415251.html
標籤:其他
下一篇:springboot 跨域配置類
