日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) >

异步接口同步返回_Dubbo客户端异步接口的实现背景和实践

發(fā)布時(shí)間:2025/4/16 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 异步接口同步返回_Dubbo客户端异步接口的实现背景和实践 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

鋪墊

先簡(jiǎn)單介紹下一次完整的Dubbo調(diào)用所經(jīng)歷的線程階段。幾個(gè)信息這里羅列下

  • Biz~代表業(yè)務(wù)線程,即便是業(yè)務(wù)邏輯處理所處的線程,Biz~線程池可能是業(yè)務(wù)自己創(chuàng)建維護(hù),大多數(shù)的可能是系統(tǒng)框架自身管理的(比如web型的業(yè)務(wù)系統(tǒng)跑在Tomcat容器下,Biz~線程就是Tomcat維護(hù));IO~代表網(wǎng)絡(luò)數(shù)據(jù)處理線程,是IO框架(比如Netty,Grizzly)創(chuàng)建維護(hù),Dubbo Remoting所默認(rèn)Netty實(shí)現(xiàn)是NioEventloopLoopGroup;另外按照Channel與IO線程的綁定關(guān)系,也可以直接把IO~看成一個(gè)可接受事件消息的Channel。像Biz和IO這樣的異步處理階段在JDK8中有個(gè)很精確地抽象描述,叫CompletionStage。
  • 大家知道,線程與線程之間做數(shù)據(jù)通信的方式是共享變量,Biz和IO兩個(gè)stage之間的數(shù)據(jù)通信是Queue,具體到Dubbo實(shí)現(xiàn),在客戶(hù)端一側(cè)的實(shí)現(xiàn)(即上圖中用1所標(biāo)注的步驟)中Biz是通過(guò)向EventLoop的LinkedBlockingQueue放置一個(gè)Task,而EventLoop有對(duì)應(yīng)的Thread會(huì)不停的迭代Queue來(lái)執(zhí)行Task中所包含的信息,具體代碼可以看SingleThreadEventExecutor(順便提下,Netty中默認(rèn)是用無(wú)上限的LinkedBlockingQueue,在Biz的速率高于網(wǎng)絡(luò)速率情況下,似乎好像有Memory Leak的風(fēng)險(xiǎn))。
  • 如上圖所示,標(biāo)準(zhǔn)的一次RPC調(diào)用經(jīng)過(guò)了圖中所示的1,2,3,4的四次消息(事件)傳遞,分別是客戶(hù)端業(yè)務(wù)線程到IO線程的請(qǐng)求發(fā)出,服務(wù)端IO線程到業(yè)務(wù)邏輯線程的__請(qǐng)求接受,__服務(wù)端處理完成后由業(yè)務(wù)邏輯線程到IO線程的響應(yīng)寫(xiě)出,客戶(hù)端收到結(jié)果后從IO線程到業(yè)務(wù)邏輯的響應(yīng)處理。除了1與4之間一般需要維護(hù)響應(yīng)和請(qǐng)求的映射對(duì)應(yīng)關(guān)系,四次的事件處理都是完全獨(dú)立的,所以一次RPC調(diào)用天然是異步的,而同步是基于異步而來(lái)。
  • 客戶(hù)端異步

    實(shí)現(xiàn)背景

    在Java語(yǔ)言(其他語(yǔ)言不清楚)下一次本地接口的調(diào)用可以透明地通過(guò)代理機(jī)制轉(zhuǎn)為遠(yuǎn)程RPC的調(diào)用,大多數(shù)業(yè)務(wù)方也比較喜歡這種與本地接口類(lèi)似的編程方式做遠(yuǎn)程服務(wù)集成,所以雖然RPC內(nèi)部天然是異步的,但使用Dubbo的用戶(hù)使用最廣泛的還是同步,而異步反而成為小眾的使用場(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)銷(xiāo)。

    所以,客戶(hù)端異步的出發(fā)點(diǎn)是節(jié)省線程資源開(kāi)銷(xiāo),代價(jià)是需要了解下異步的使用方式:)。在同步方式下API接口的返回類(lèi)型是代表著某個(gè)業(yè)務(wù)類(lèi),而當(dāng)異步情況下,響應(yīng)返回與請(qǐng)求發(fā)出是完全獨(dú)立的兩個(gè)事件,需要API接口的返回類(lèi)型變?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)依賴(lài)結(jié)果:異步回調(diào)是在客戶(hù)端非強(qiáng)依賴(lài)服務(wù)端的結(jié)果情況下,是適用客戶(hù)端的異步調(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),才能使得用戶(hù)更自然地適用異步接口。

    小結(jié)

    • 客戶(hù)端異步的出發(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)題。

    如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。