异步接口同步返回_Dubbo客户端异步接口的实现背景和实践
鋪墊
先簡(jiǎn)單介紹下一次完整的Dubbo調(diào)用所經(jīng)歷的線程階段。幾個(gè)信息這里羅列下
客戶端異步
實(shí)現(xiàn)背景
在Java語(yǔ)言(其他語(yǔ)言不清楚)下一次本地接口的調(diào)用可以透明地通過(guò)代理機(jī)制轉(zhuǎn)為遠(yuǎn)程RPC的調(diào)用,大多數(shù)業(yè)務(wù)方也比較喜歡這種與本地接口類似的編程方式做遠(yuǎn)程服務(wù)集成,所以雖然RPC內(nèi)部天然是異步的,但使用Dubbo的用戶使用最廣泛的還是同步,而異步反而成為小眾的使用場(chǎng)景。同步的優(yōu)點(diǎn)是編程模型更加符合業(yè)務(wù)方的“傳統(tǒng)”習(xí)慣,代價(jià)是在圖中的1代表的請(qǐng)求發(fā)出事件后需要阻塞當(dāng)前的Biz~線程,一直等到4代表的響應(yīng)處理后才能喚醒。在這個(gè)短則微秒級(jí)別,長(zhǎng)則秒級(jí)的1,2,3,4處理過(guò)程中都要阻塞Biz~線程,就會(huì)消耗線程資源,增加系統(tǒng)資源的開(kāi)銷。
所以,客戶端異步的出發(fā)點(diǎn)是節(jié)省線程資源開(kāi)銷,代價(jià)是需要了解下異步的使用方式:)。在同步方式下API接口的返回類型是代表著某個(gè)業(yè)務(wù)類,而當(dāng)異步情況下,響應(yīng)返回與請(qǐng)求發(fā)出是完全獨(dú)立的兩個(gè)事件,需要API接口的返回類型變?yōu)樯鲜鲋姓f(shuō)的CompletionStage才是最貼合的,這是Dubbo在異步上支持的必然異步。回到最近的Dubbo發(fā)布版,是不改變接口的情況下,需要在服務(wù)創(chuàng)建時(shí)注冊(cè)一個(gè)回調(diào)接口來(lái)處理響應(yīng)返回事件。
下面以示例來(lái)說(shuō)。
示例
事件通知的示例代碼請(qǐng)參考:https://github.com/dubbo/dubbo-samples/tree/master/dubbo-samples-notify
事件通知允許 Consumer 端在調(diào)用之前、調(diào)用正常返回之后或調(diào)用出現(xiàn)異常時(shí),觸發(fā) oninvoke、onreturn、onthrow 三個(gè)事件。
可以通過(guò)在配置 Consumer 時(shí),指定事件需要通知的方法,如:
<bean id="demoCallback" class="com.alibaba.dubbo.samples.notify.impl.NotifyImpl" /><dubbo:reference id="demoService" check="false" interface="com.alibaba.dubbo.samples.notify.api.DemoService" version="1.0.0" group="cn"><dubbo:method name="sayHello" onreturn="demoCallback.onreturn" onthrow="demoCallback.onthrow"/> </dubbo:reference>其中,NotifyImpl 的代碼如下:
public class NotifyImpl implements Notify{public Map<Integer, String> ret = new HashMap<Integer, String>();public void onreturn(String name, int id) {ret.put(id, name);System.out.println("onreturn: " + name);}public void onthrow(Throwable ex, String name, int id) {System.out.println("onthrow: " + name);} }這里要強(qiáng)調(diào)一點(diǎn),自定義 Notify 接口中的三個(gè)方法的參數(shù)規(guī)則如下:
- oninvoke 方法參數(shù)與調(diào)用方法的參數(shù)相同;
- onreturn方法第一個(gè)參數(shù)為調(diào)用方法的返回值,其余為調(diào)用方法的參數(shù);
- onthrow方法第一個(gè)參數(shù)為調(diào)用異常,其余為調(diào)用方法的參數(shù)。
上述配置中,sayHello方法為同步調(diào)用,因此事件通知方法的執(zhí)行也是同步執(zhí)行。可以配置 async=true讓方法調(diào)用為異步,這時(shí)事件通知的方法也是異步執(zhí)行的。特別強(qiáng)調(diào)一下,oninvoke方法不管是否異步調(diào)用,都是同步執(zhí)行的。
實(shí)踐建議
- RPC調(diào)用后的邏輯非強(qiáng)依賴結(jié)果:異步回調(diào)是在客戶端非強(qiáng)依賴服務(wù)端的結(jié)果情況下,是適用客戶端的異步調(diào)用。
- rx場(chǎng)景:自從了解到reactive的編程模型后,認(rèn)為只要編程思維能夠擁抱reactive,并且業(yè)務(wù)模型的狀態(tài)機(jī)設(shè)計(jì)能做適當(dāng)?shù)恼{(diào)整,任何場(chǎng)景下都比較適用異步來(lái)解決,從而得到更好的終端響應(yīng)體驗(yàn)。 對(duì)于Dubbo來(lái)說(shuō),當(dāng)下的異步接口模型是需要像reactive的模型接口做改進(jìn),才能使得用戶更自然地適用異步接口。
小結(jié)
- 客戶端異步的出發(fā)點(diǎn)就是請(qǐng)求發(fā)出和響應(yīng)處理本身為兩個(gè)不同的獨(dú)立事件,響應(yīng)如何被處理和在哪個(gè)線程中處理等都是不需要和請(qǐng)求發(fā)出事件的業(yè)務(wù)邏輯線程做耦合綁定。
- 響應(yīng)事件回調(diào)的處理邏輯在哪個(gè)線程中做處理是需要根據(jù)情況來(lái)選擇。建議,如果回調(diào)邏輯比較簡(jiǎn)單,建議直接在IO線程中;如果包含了遠(yuǎn)程訪問(wèn)或者DB訪問(wèn)等IO型的__同步__操作,建議在獨(dú)立的線程池做處理。
總結(jié)
以上是生活随笔為你收集整理的异步接口同步返回_Dubbo客户端异步接口的实现背景和实践的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: pip安装ipython_Python
- 下一篇: python csv转excel_使用