Java知识分享
热爱技术,分享技术

Dubbo服务消费者异步调用服务

什么是同步调用,也就是说调用线程在服务提供方结果返回前需要被阻塞,异步调用则是说消费者发起调用后会马上返回。本篇我们将介绍两种异步调用方式。

1. Dubbo 2.6.*版本提供的异步调用

首先我们看看第一种异步调用方式:首先写一个消费者基类

package cn.hackcloud.demo.dubbo;
import com.alibaba.fastjson.JSON;
import org.apache.dubbo.config.ApplicationConfig;
import org.apache.dubbo.config.ReferenceConfig;
import org.apache.dubbo.config.RegistryConfig;

public class BasConsumer {

public static <T> ReferenceConfig<T> referenceConfig() {
//1.创建引用实例,并设置属性
ReferenceConfig<T> reference = new ReferenceConfig<>();
reference.setApplication(new ApplicationConfig("consumer"));
reference.setRegistry(new RegistryConfig("zookeeper://127.0.0.1:2181"));
reference.setInterface("cn.hackcloud.demo.dubbo.rpc.IUserService");
reference.setGroup("hackcloud");
reference.setVersion("1.0");
return reference;
}

static void print(Object o) {
System.out.println(JSON.toJSONString(o));
}
}
/**
 * 2.6版本异步调用
 *
 * @throws ExecutionException
 * @throws InterruptedException
 */
public static void async() throws ExecutionException, InterruptedException {
    ReferenceConfig<IUserService> reference = referenceConfig();
    //2设置为异步
    reference.setAsync(true);
    //3.直接返回null
    IUserService userService = reference.get();
    System.out.println(userService.sync("1"));
    //4.等待结果
    Future future = RpcContext.getContext().getFuture();
    print(future.get());
}

代码1创建引用实例,并且设置属性。代码2设置为异步调用。代码3进行服务引用并且调用sync方法,由于是异步调用,所以改方法马上返回null,代码4使用RpcContext.getContext().getFuture()对象,然后在需要获取真实响应的地方调用future.get()获取响应结果。

缺点:调用future.get()方法会使线程一直阻塞。

2. Dubbo 2.6.* 基于异步回调的方式调用

/**
 * 2.6异步回调
 */
public static void asyncCallBack() {
    ReferenceConfig<IUserService> reference = referenceConfig();
    //2设置为异步
    reference.setAsync(true);
    IUserService userService = reference.get();
    //3.直接返回null
    System.out.println(userService.sync("1"));
    FutureAdapter adapter = (FutureAdapter)     RpcContext.getContext().getFuture();
   //4.回调函数
    adapter.getFuture().setCallback(new ResponseCallback() {
        @Override
        public void done(Object response) {
            print(response);
        }

        @Override
        public void caught(Throwable exception) {

        }
    });
}

上面代码不同之处在于代码4,在FutureAdapter adapter =(FutureAdapter)RpcContext.getContext().getFuture().getFuture();获取的future对象上可以调用setCallBack()方法设置一个回调函数,该回调函数有2个方法,当远端正常返回响应结果后,会回调done()方法,其参数response就是响应结果值,当发起远程调用发生错误时会回调caught()方法以打印错误信息。

设置回调的这种方式不会阻塞业务线程,这是由于借助了Netty的异步通信机制,Netty底层的I/O线程会在接收到响应后自动回调注册的回调函数啊,不需要业务线程干预。

3. Dubbo 2.7.* 版本提供的异步调用

上面我们写了2个示例代码测试了Dubbo 2.7.0之前提供的异步调用方式,Future方式只支持阻塞式的get()接口获取结果,芮然通过获取内置的ResponseFuture接口可以设置回调,但获取ResponseFuture的API使用起来不方便,并且无法满足让多个Future协同工作的场景,功能比较单一。

基于Dubbo 2.7.0版本提供的CompletableFuture的异步调用代码如下:

/**
 * 2.7异步回调
 */
public static void asyncCallBackNew() {
ReferenceConfig<IUserService> reference = referenceConfig();
//设置为异步
reference.setAsync(true);
IUserService userService = reference.get();
userService.async("1");
//4.异步执行回调
CompletableFuture<Object> completableFuture = RpcContext.getContext().getCompletableFuture();
completableFuture.whenComplete((v, t) -> {
print(v);
});
}

上面代码4直接使用RpcContext.getContext().getCompletableFuture();

获取CompletableFuture类型的future,然后就可以基于CompletableFuture的能力做一些操作。这里调用whenComplete方法设置了回调函数,作用是当服务提供端产生响应结果后调用设置的回调函数,函数内判断如果异常t不为null,则打印异常信息,否则打印响应结果。

Dubbo服务消费者异步调用服务插图
打赏
本站所有资源均来源于网络,仅供学习使用,请支持正版!Java技术开源 » Dubbo服务消费者异步调用服务

评论 抢沙发

评论前必须登录!

 

觉得文章有用就打赏一下文章作者

非常感谢你的打赏,我们将继续提供更多优质内容,让我们一起创建更加美好的网络世界!

支付宝扫一扫

微信扫一扫

登录

找回密码

注册