异步调用

    从 2.7.0 开始,Dubbo 的所有异步编程接口开始以 CompletableFuture 为基础

    基于 NIO 的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小。

    需要服务提供者事先定义 CompletableFuture 签名的服务,具体参见接口定义:

    注意接口的返回类型是 。

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

    调用远程服务:

    1. // 调用直接返回CompletableFuture
    2. CompletableFuture<String> future = asyncService.sayHello("async call request");
    3. // 增加回调
    4. future.whenComplete((v, t) -> {
    5. if (t != null) {
    6. t.printStackTrace();
    7. } else {
    8. System.out.println("Response: " + v);
    9. }
    10. });
    11. // 早于结果输出

    在 consumer.xml 中配置:

    调用代码:

    1. // 此调用会立即返回null
    2. // 拿到调用的Future引用,当结果返回后,会被通知和设置到此Future
    3. CompletableFuture<String> helloFuture = RpcContext.getContext().getCompletableFuture();
    4. // 为Future添加回调
    5. helloFuture.whenComplete((retValue, exception) -> {
    6. if (exception == null) {
    7. System.out.println(retValue);
    8. } else {
    9. exception.printStackTrace();
    10. }
    11. });

    或者,你也可以这样做异步调用:

    1. CompletableFuture<String> future = RpcContext.getContext().asyncCall(
    2. () -> {
    3. asyncService.sayHello("oneway call request1");
    4. future.get();

    如果你只有这样的同步服务定义,而又不喜欢 RpcContext 的异步使用方式。

    有两种方式来实现:

    1. 提供方或消费方自己修改接口签名
    1. public interface GreetingsService {
    2. String sayHi(String name);
    3. // AsyncSignal is totally optional, you can use any parameter type as long as java allows your to do that.
    4. default CompletableFuture<String> sayHi(String name, AsyncSignal signal) {
    5. return CompletableFuture.completedFuture(sayHi(name));
    6. }
    7. }
    1. Dubbo 官方提供 compiler hacker,编译期自动重写同步方法,请在此讨论和跟进具体进展。

    你也可以设置是否等待消息发出:

    • sent="true" 等待消息发出,消息发送失败将抛出异常。
    • sent="false" 不等待消息发出,将消息放入 IO 队列,即刻返回。

      如果你只是想异步,完全忽略返回值,可以配置 return="false",以减少 Future 对象的创建和管理成本:


      1. 异步总是不等待返回 ↩︎

      最后修改 September 21, 2021: