Dubbo異步方法調用里有個坑

Dubbo是一個分布式服務框架,是阿里巴巴SOA服務化治理方案的核心框架。
?使用Dubbo進行服務化后速缨,現有如下場景時序圖:



場景描述:客戶端遠程異步調用ServiceA,ServiceA在處理客戶端請求的過程中需要遠程同步調用ServiceB旬牲,ServiceA從ServiceB的響應中取數據時,得到的是null摩骨,對就是這個坑唤冈。

使用DEBUG模式,分析Dubbo源碼得到問題的起因啄栓。
分析過程如下:
客戶端和服務端通信奖亚,配置使用netty進行網絡傳輸淳梦,通過
NettyHandler進行具體的消息收發(fā)操作,所以從此入手進行源碼分析昔字。
client到ServiceA的遠程方法異步調用爆袍,會在RpcContext(RpcContext是一個臨時狀態(tài)記錄器,當接收到RPC請求李滴,或發(fā)起RPC請求時螃宙,RpcContext的狀態(tài)都會變化。比如:A調B所坯,B再調C谆扎,則B機器上,在B調C之前芹助,RpcContext記錄的是A調B的信息堂湖,在B調C之后闲先,RpcContext記錄的是B調C的信息)的attachments(Map結構)屬性中添加async=true的鍵值對,同時也會在RpcInvocation的attachments(Map結構)中添加async=true的鍵值對无蜂。
經過一系列的Filter伺糠,程序運行到AbstractInvoker的invoke方法,注意該方法中的如下代碼段斥季,
Map<String, String> context = RpcContext.getContext().getAttachments();
if (context != null) {
invocation.addAttachmentsIfAbsent(context);
}
這里會把當前RpcContext中的attachments添加到調用ServiceB的RpcInvocation中训桶,這時候async=true已經添加了,接著執(zhí)行如下代碼段酣倾,
if (getUrl().getMethodParameter(invocation.getMethodName(), Constants.ASYNC_KEY, false)){
invocation.setAttachment(Constants.ASYNC_KEY, Boolean.TRUE.toString());
}
上面代碼判斷調用ServiceB的URL中是否含有async=true舵揭,如果有將設置async=true到RpcInvocation的attachments中,這時候是不包含的躁锡。
繼續(xù)跟蹤代碼午绳,運行到DubboInvoker中,調用doInvoke方法映之,該方法中有如下的代碼段拦焚,boolean isAsync = RpcUtils.isAsync(getUrl(), invocation),這個isAsync方法具體聲明如下杠输,
public static boolean isAsync(URL url, Invocation inv) {
boolean isAsync ;
//如果Java代碼中設置優(yōu)先.
if (Boolean.TRUE.toString().equals(inv.getAttachment(Constants.ASYNC_KEY))) {
isAsync = true;
} else {
isAsync = url.getMethodParameter(getMethodName(inv), Constants.ASYNC_KEY, false);
}
return isAsync;
}
上面方法首先判斷RpcInvocation的attachments中async=true是否成立赎败,如果成立則這是一次異步調用,否則判斷請求URL中async=true是否成立抬伺,如果成立則是一次異步調用螟够,否則是一次同步調用,根據上面?zhèn)鬟f的參數峡钓,此時isAsync方法返回的是true妓笙,ServiceA同步調用ServiceB變成了異步調用,繼續(xù)看下面的異步調用能岩,代碼段如下寞宫,
else if (isAsync) {
ResponseFuture future = currentClient.request(inv, timeout) ;
RpcContext.getContext().setFuture(new FutureAdapter<Object>(future));
return new RpcResult();
}
這里直接返回了一個RpcResult對象,沒有數據內容拉鹃,所以到這里辈赋,這個案子也就破了,ServiceA想從響應中取目標數據得到的當然是null膏燕。再延伸一下钥屈,如果ServiceB再同步調用ServiceC,這是可以正常同步調用的坝辫,因為ServiceA調用完ServiceB后篷就,ConsumerContextFilter的invoke方法會清除attachements,所以ServiceB可以正常同步調用ServiceC了近忙。

對于上面的問題竭业,解決辦法有三個:
1.方法調用兩次
ServiceA調用ServiceB的地方寫兩次一樣的調用智润,這個方法原理就像ServiceB調用ServiceC一樣,即清除attachements未辆,這個方法最簡單窟绷,但是可能對不了解的人來說,這塊業(yè)務代碼寫重復了咐柜,會不小心刪除掉兼蜈,而且從寫代碼的角度來說,這個很雞肋炕桨,所以不推薦饭尝。
2.修改Dubbo源碼
修改AbstractInvoker第137行,改成每次都對async進行實際賦值献宫,
boolean isAsync = getUrl().getMethodParameter(invocation.getMethodName(), Constants.ASYNC_KEY, false);
invocation.setAttachment(Constants.ASYNC_KEY, String.valueOf(isAsync));
3.自定義Filter
實現com.alibaba.dubbo.rpc.Filter,在RpcContext中清除這個async实撒,
@Activate(group = {Constants.PROVIDER})
public class AsyncFilter implements Filter {
@Override
public Result invoke(Invoker<?> invoker, Invocation invocation) throws RpcException {
RpcContext.getContext().getAttachments().remove(Constants.ASYNC_KEY);
return invoker.invoke(invocation);
}
}
同時在src/main/resources/META-INF/dubbo/下添加com.alibaba.dubbo.rpc.Filter文件姊途,內容文件如下:
asyncFilter=com.abc.filter.AsyncFilter

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市知态,隨后出現的幾起案子捷兰,更是在濱河造成了極大的恐慌,老刑警劉巖负敏,帶你破解...
    沈念sama閱讀 211,265評論 6 490
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件贡茅,死亡現場離奇詭異,居然都是意外死亡其做,警方通過查閱死者的電腦和手機顶考,發(fā)現死者居然都...
    沈念sama閱讀 90,078評論 2 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來妖泄,“玉大人驹沿,你說我怎么就攤上這事〉负” “怎么了渊季?”我有些...
    開封第一講書人閱讀 156,852評論 0 347
  • 文/不壞的土叔 我叫張陵,是天一觀的道長罚渐。 經常有香客問我却汉,道長,這世上最難降的妖魔是什么荷并? 我笑而不...
    開封第一講書人閱讀 56,408評論 1 283
  • 正文 為了忘掉前任合砂,我火速辦了婚禮,結果婚禮上璧坟,老公的妹妹穿的比我還像新娘既穆。我一直安慰自己赎懦,他們只是感情好,可當我...
    茶點故事閱讀 65,445評論 5 384
  • 文/花漫 我一把揭開白布幻工。 她就那樣靜靜地躺著励两,像睡著了一般。 火紅的嫁衣襯著肌膚如雪囊颅。 梳的紋絲不亂的頭發(fā)上当悔,一...
    開封第一講書人閱讀 49,772評論 1 290
  • 那天,我揣著相機與錄音踢代,去河邊找鬼盲憎。 笑死,一個胖子當著我的面吹牛胳挎,可吹牛的內容都是我干的饼疙。 我是一名探鬼主播,決...
    沈念sama閱讀 38,921評論 3 406
  • 文/蒼蘭香墨 我猛地睜開眼慕爬,長吁一口氣:“原來是場噩夢啊……” “哼窑眯!你這毒婦竟也來了?” 一聲冷哼從身側響起医窿,我...
    開封第一講書人閱讀 37,688評論 0 266
  • 序言:老撾萬榮一對情侶失蹤磅甩,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后姥卢,有當地人在樹林里發(fā)現了一具尸體卷要,經...
    沈念sama閱讀 44,130評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 36,467評論 2 325
  • 正文 我和宋清朗相戀三年独榴,在試婚紗的時候發(fā)現自己被綠了僧叉。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 38,617評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡括眠,死狀恐怖彪标,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情掷豺,我是刑警寧澤捞烟,帶...
    沈念sama閱讀 34,276評論 4 329
  • 正文 年R本政府宣布,位于F島的核電站当船,受9級特大地震影響题画,放射性物質發(fā)生泄漏。R本人自食惡果不足惜德频,卻給世界環(huán)境...
    茶點故事閱讀 39,882評論 3 312
  • 文/蒙蒙 一苍息、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦竞思、人聲如沸表谊。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,740評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽爆办。三九已至,卻和暖如春课梳,著一層夾襖步出監(jiān)牢的瞬間距辆,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 31,967評論 1 265
  • 我被黑心中介騙來泰國打工暮刃, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留跨算,地道東北人。 一個月前我還...
    沈念sama閱讀 46,315評論 2 360
  • 正文 我出身青樓椭懊,卻偏偏與公主長得像诸蚕,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子灾搏,可洞房花燭夜當晚...
    茶點故事閱讀 43,486評論 2 348

推薦閱讀更多精彩內容