dubbo-8:异步调用

10 篇文章 1 订阅

官方说明
Dubbo不只提供了堵塞式的的同步调用,同时提供了异步调用的方式。

这种方式主要应用于提供者接口响应耗时明显,消费者端可以利用调用接口的时间去做一些其他的接口调用,利用 Future 模式来异步等待和获取结果即可。

这种方式可以大大的提升消费者端的利用率。 目前这种方式可以通过XML的方式进行引入。

由于注解模式下不支持方法级别的method属性设置,所以这个demo测试,使用xml模式

1、模拟等待

为了模拟等待,通过 int timeMills参数,标明需要休眠多少毫秒后才会进行返回。

public interface HelloService {
    String sayHello(String name, int timeMills);
}

2、服务端接口实现

让线程等待一段时间

package com.lagou.service.impl;

import com.lagou.service.HelloService;

public class HelloServiceImpl implements HelloService {
    public String sayHello(String name, int timeMills) {
        try {
            Thread.sleep(timeMills);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "【我是服务端】hello1111:" + name;
    }
}

其他配置详见基本案例(XML版)
dubbo-provider.xml
ProviderApplication.java

3、消费者端接口调用

配置异步调用

  <dubbo:method name="sayHello" async="true"/>

完整如下:

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xmlns:dubbo="http://dubbo.apache.org/schema/dubbo"
       xsi:schemaLocation="http://www.springframework.org/schema/beans
       http://www.springframework.org/schema/beans/spring-beans-4.3.xsd
       http://dubbo.apache.org/schema/dubbo
       http://dubbo.apache.org/schema/dubbo/dubbo.xsd">

    <!-- 消费方应用名,用于计算依赖关系,不是匹配条件,不要与提供方一样 -->
    <dubbo:application name="service-consumer" >
        <dubbo:parameter key="qos.enable" value="true" ></dubbo:parameter>
        <dubbo:parameter key="qos.port" value="33333"></dubbo:parameter>
        <!-- value为true:talnet用ip登录之后可以操作,否则只能登录不能操作-->
        <dubbo:parameter key="qos.accept.foreign.ip" value="true" ></dubbo:parameter>

    </dubbo:application>

    <!-- 使用zookeeper注册中心暴露发现服务地址 -->
    <dubbo:registry address="zookeeper://127.0.0.1:2181" />

    <!-- 生成远程服务代理,可以和本地bean一样使用demoService -->
    <dubbo:reference id="helloService" interface="com.lagou.service.HelloService" >
        <!-- 设置方法是否异步调用 :默认是false。
        TODO 注意:方法在异步调用时的返回值是空,我们可以通过 RpcContext.getContext().getFuture()
                 获取Future对象,来进行后续的结果等操作
        -->
        <dubbo:method name="sayHello" async="true"/>
    </dubbo:reference>
</beans>

4、测试

我们休眠100毫秒,然后再去进行获取结果。方法在同步调用时的返回值是空,我们可以通过 RpcContext.getContext().getFuture() 来进行获取Future对象来进行后续的结果等待操作。

package com.lagou;

import com.lagou.service.HelloService;
import org.apache.dubbo.rpc.RpcContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;

import java.util.concurrent.Future;


public class AsyncConsumerApplication {
    public static void main(String[] args) throws Exception {
        ClassPathXmlApplicationContext context = new ClassPathXmlApplicationContext("classpath:dubbo-consumer.xml");
        System.out.println("Consumer 启动成功!");
        HelloService helloService = (HelloService) context.getBean("helloService"); // 获取远程服务代理
        System.out.println("获取接口成功!");

        while (true) {
            System.in.read();
            String hello = helloService.sayHello("world", 100); // 执行远程方法
            // 利用Future 模式来获取
            Future<Object> future = RpcContext.getContext().getFuture();
            System.out.println("result:" + hello); // 直接显示:结果为null
            System.out.println("future===》result:" + future.get()); // 用future,结果可以争取获取到
        }
    }
}

测试结果如下:
在这里插入图片描述

5、注意

方法在异步调用时的返回值是空,我们可以通过 RpcContext.getContext().getFuture() 获取Future对象,来进行后续的结果等操作。详见第4步测试类中的具体代码
在这里插入图片描述

6、特殊说明

需要特别说明的是,该方式的使用,请确保dubbo的版本在2.5.4及以后的版本使用。 原因在于在2.5.3及之前的版本使用的时候,会出现异步状态传递问题。

比如我们的服务调用关系是 A -> B -> C , 这时候如果A向B发起了异步请求,在错误的版本时,B向C发起的请求也会连带的产生异步请求。这是因为在底层实现层面,他是通过 RPCContext 中的attachment 实现的。在A向B发起异步请求时,会在 attachment 中增加一个异步标示字段来表明异步等待结果。B在接受到A中的请求时,会通过该字段来判断是否是异步处理。但是由于值传递问题,B向C发起时同样会将该值进行传递,导致C误以为需要异步结果,导致返回空。这个问题在2.5.4及以后的版本进行了修正

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值