Dubbo3 異步調(diào)用

2022-03-31 15:38 更新

在 Dubbo 中發(fā)起異步調(diào)用

從 2.7.0 開始,Dubbo 的所有異步編程接口開始以 CompletableFuture  為基礎(chǔ)

基于 NIO 的非阻塞實現(xiàn)并行調(diào)用,客戶端不需要啟動多線程即可完成并行調(diào)用多個遠(yuǎn)程服務(wù),相對多線程開銷較小。

/user-guide/images/future.jpg

使用 CompletableFuture 簽名的接口

需要服務(wù)提供者事先定義 CompletableFuture 簽名的服務(wù),具體參見服務(wù)端異步執(zhí)行接口定義:

public interface AsyncService {
    CompletableFuture<String> sayHello(String name);
}

注意接口的返回類型是? CompletableFuture<String>?。

XML引用服務(wù):

<dubbo:reference id="asyncService" timeout="10000" interface="com.alibaba.dubbo.samples.async.api.AsyncService"/>

調(diào)用遠(yuǎn)程服務(wù):

// 調(diào)用直接返回CompletableFuture
CompletableFuture<String> future = asyncService.sayHello("async call request");
// 增加回調(diào)
future.whenComplete((v, t) -> {
    if (t != null) {
        t.printStackTrace();
    } else {
        System.out.println("Response: " + v);
    }
});
// 早于結(jié)果輸出
System.out.println("Executed before response return.");

使用 RpcContext

在 consumer.xml 中配置:

<dubbo:reference id="asyncService" interface="org.apache.dubbo.samples.governance.api.AsyncService">
      <dubbo:method name="sayHello" async="true" />
</dubbo:reference>

調(diào)用代碼:

// 此調(diào)用會立即返回null
asyncService.sayHello("world");
// 拿到調(diào)用的Future引用,當(dāng)結(jié)果返回后,會被通知和設(shè)置到此Future
CompletableFuture<String> helloFuture = RpcContext.getContext().getCompletableFuture();
// 為Future添加回調(diào)
helloFuture.whenComplete((retValue, exception) -> {
    if (exception == null) {
        System.out.println(retValue);
    } else {
        exception.printStackTrace();
    }
});

或者,你也可以這樣做異步調(diào)用:

CompletableFuture<String> future = RpcContext.getContext().asyncCall(
    () -> {
        asyncService.sayHello("oneway call request1");
    }
);

future.get();

重載服務(wù)接口

如果你只有這樣的同步服務(wù)定義,而又不喜歡 RpcContext 的異步使用方式。

public interface GreetingsService {
    String sayHi(String name);
}

那還有一種方式,就是利用 Java 8 提供的 default 接口實現(xiàn),重載一個帶有 CompletableFuture 簽名的方法。

CompletableFuture 簽名的方法目前只支持 Dubbo 協(xié)議,其他協(xié)議由于第三方實現(xiàn)問題,需要視具體情況而定。

有兩種方式來實現(xiàn):

  1. 提供方或消費方自己修改接口簽名
public interface GreetingsService {
    String sayHi(String name);
    
    // AsyncSignal is totally optional, you can use any parameter type as long as java allows your to do that.
    default CompletableFuture<String> sayHi(String name, AsyncSignal signal) {
        return CompletableFuture.completedFuture(sayHi(name));
    }
}
  1. Dubbo 官方提供 compiler hacker,編譯期自動重寫同步方法,請在此討論和跟進(jìn)具體進(jìn)展。

你也可以設(shè)置是否等待消息發(fā)出(異步總是不等待返回): 

  • ?sent="true"? 等待消息發(fā)出,消息發(fā)送失敗將拋出異常。
  • ?sent="false" ?不等待消息發(fā)出,將消息放入 IO 隊列,即刻返回。
<dubbo:method name="findFoo" async="true" sent="true" />

如果你只是想異步,完全忽略返回值,可以配置 ?return="false"?,以減少 Future 對象的創(chuàng)建和管理成本:

<dubbo:method name="findFoo" async="true" return="false" />


以上內(nèi)容是否對您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號
微信公眾號

編程獅公眾號