dubbo入门之异步调用
dubbo默认使用同步的方式调用。但在有些特殊的场景下,我们可能希望异步调用dubbo接口,从而避免不必要的等待时间,这时候我们就需要用到异步。那么dubbo的异步是如何实现的呢?下面就来看看这个问题
异步方法配置:
<dubbo:reference cache="lru" id="demoService" interface="com.ping.chen.dubbo.service.DemoService" timeout="5000">
<dubbo:method name="sayHello" async="true"/>
</dubbo:reference>
底层的异步处理实现在DubboInvoker的doInvoke方法中,源码如下:
protected Result doInvoke(final Invocation invocation) throws Throwable {
RpcInvocation inv = (RpcInvocation) invocation;
忽略Attachment设置。。。
try {
// 是否异步执行
boolean isAsync = RpcUtils.isAsync(getUrl(), invocation);
boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);//是否单向执行
int timeout = getUrl().getMethodParameter(methodName, Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);//接口超时时间,默认1秒
if (isOneway) {
boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
currentClient.send(inv, isSent);
RpcContext.getContext().setFuture(null);
return new RpcResult();
} else if (isAsync) {//异步
ResponseFuture future = currentClient.request(inv, timeout);
RpcContext.getContext().setFuture(new FutureAdapter<Object>(future));
return new RpcResult();
} else {
RpcContext.getContext().setFuture(null);
return (Result) currentClient.request(inv, timeout).get();
}
} catch (TimeoutException e) {
//异常处理。。。
}
}
可以看到,如果异步执行,会直接返回一个空的RpcResult,然后用户如果需要异步执行结果,可以从RpcContext中的Future中去获取,直接用RpcContext.getContext().getFuture().get();就可以获取到执行结果。那么RpcContext是如何保证当前线程可以拿到执行结果呢?答案是ThreadLocal。我们来看看RpcContext源码如下:
public class RpcContext {
private static final ThreadLocal<RpcContext> LOCAL = new ThreadLocal<RpcContext>() {
@Override
protected RpcContext initialValue() {
return new RpcContext();
}
};
public static RpcContext getContext() {
return LOCAL.get();
}
。。。。。。
}
可以看到RpcContext 内部是使用ThreadLocal来实现的。
异步可能遇到的坑
上面这种配置有一个坑,可能你会像下面这样使用异步:
@RestController
public class DemoController {
@Reference(timeout = 5000)
DemoProvider demoProvider;
@RequestMapping("/demo")
public void demo() throws ExecutionException, InterruptedException {
demoProvider.sayHello("world");
System.out.println(">>>>>>>>>>" + RpcContext.getContext().getFuture().get());
}
}
然后请求demo接口的时候,很不幸,你将会收到一个NullPointException,这因为我们只在消费者端配置了异步执行,但服务端执行的时候是同步的,所以我们从RpcContext中获取到的Future是空的,正确的异步配置应该是:
直接去掉消费者端的
<dubbo:method name="sayHello" async="true"/>
配置,然后在服务提供者端做如下配置:
<!-- 声明需要暴露的服务接口 -->
<dubbo:service interface="com.ping.chen.dubbo.provider.DemoProvider" ref="demoProvider" >
<dubbo:method name="sayHello" async="true"/>
</dubbo:service>
如此,便可以实现异步了
dubbo入门之异步调用的更多相关文章
- 使用rabbit mq.模拟dubbo,使MQ异步调用代码写起来像是同步方法.
最近在改造老系统,遇到了需要使用rabbitMq的场景.在以前使用的过程中需要在发送端和消费端各种配置,感觉比较麻烦,然后突然想到了dubbo中@Reference注解的形式,可不可以做一个类似的架子 ...
- Dubbo中CompletableFuture异步调用
使用Future实现异步调用,对于无需获取返回值的操作来说不存在问题,但消费者若需要获取到最终的异步执行结果,则会出现问题:消费者在使用Future的get()方法获取返回值时被阻塞.为了解决这个问题 ...
- Dubbo学习笔记4:服务消费端泛化调用与异步调用
本文借用dubbo.learn的Dubbo API方式来解释原理. 服务消费端泛化调用 前面我们讲解到,基于Spring和基于Dubbo API方式搭建简单的分布式系统时,服务消费端引入了一个SDK二 ...
- dubbo同步/异步调用的方式
我们知道,Dubbo 缺省协议采用单一长连接,底层实现是 Netty 的 NIO 异步通讯机制:基于这种机制,Dubbo 实现了以下几种调用方式: 同步调用(默认) 异步调用 参数回调 事件通知 同步 ...
- 9.4 dubbo异步调用原理
9.1 客户端发起请求源码.9.2 服务端接收请求消息并发送响应消息源码.9.3 客户端接收响应信息(异步转同步的实现) 分析了dubbo同步调用的源码,现在来看一下dubbo异步调用. 一.使用方式 ...
- 限时购校验小工具&dubbo异步调用实现限
本文来自网易云社区 作者:张伟 背景 限时购是网易考拉目前比较常用的促销形式,但是前期创建一个限时购活动时需要各个BU按照指定的Excel格式进行选品提报,为了保证提报数据准确,运营需要人肉校验很多信 ...
- dubbo之异步调用
异步调用 基于 NIO 的非阻塞实现并行调用,客户端不需要启动多线程即可完成并行调用多个远程服务,相对多线程开销较小. 在 consumer.xml 中配置: <dubbo:reference ...
- dubbo同步调用、异步调用和是否返回结果源码分析和实例
0. dubbo同步调用.异步调用和是否返回结果配置 (1)dubbo默认为同步调用,并且有返回结果. (2)dubbo异步调用配置,设置 async="true",异步调用可以提 ...
- Dubbo消费者异步调用Future使用
Dubbo的四大组件工作原理图,其中消费者调用提供者采用的是同步调用方式.消费者对于提供者的调用,也可以采用异步方式进行调用.异步调用一般应用于提供者提供的是耗时性IO服务 一.Future异步执行原 ...
随机推荐
- 小程序图片在安卓上拉伸的问题&导航&返回首页
今天提了一个bug,有几张图片在安卓上面加载会先变大拉伸再恢复正常 出现这样的问题应该是用widthFix造成的 具体原因还不是很清楚,因为都是本地图片,所以我就直接把高也设置好就暂时没有这个问题 ...
- Linux中目录结构以及VI编辑器常见的命令操作
1.每个目录的详细介绍,先放一张目录的整体结构在这里 /bin:是Binary的缩写,用于存放经常使用的命令 /sbin:s代表Super User,用于存放系统管理员使用的命令 /home:存放普通 ...
- Thunar 右键菜单等自定义
Thunar 右键菜单等自定义 可以使用图形界面或者直接编辑配置文件,二者是等价的. 图形界面: 以给"zip,rar,7z"等文件添加"在此位置使用unar解压缩&qu ...
- 【学术篇】CF833B TheBakery 分治dp+主席树
题目の传送门~ 题目大意: 将\(n\)个蛋糕分成恰好\(k\)份, 求每份中包含的蛋糕的种类数之和的最大值. 这题有两种做法. 第一种是线段树优化dp, 我还没有考虑. 另一种就是分治+主席树. 然 ...
- pair queue____多源图广搜
.简介 class pair ,中文译为对组,可以将两个值视为一个单元.对于map和multimap,就是用pairs来管理value/key的成对元素.任何函数需要回传两个值,也需要pair. 该函 ...
- 【错误总结】Component template should contain exactly one root element. If you are using v-if on multiple elements, use v-else-if to chain them instead.
大致意思是因为模板里面应该包含一个根元素,使用组件的时候应该用div或p标签包起来
- 【leetcode】973. K Closest Points to Origin
题目如下: We have a list of points on the plane. Find the Kclosest points to the origin (0, 0). (Here, ...
- microservice-cloud-03-provider-product-8001
server: port: 8001 mybatis: config-location: classpath:mybatis/mybatis.cfg.xml # mybatis配置文 ...
- PHP FILTER_SANITIZE_SPECIAL_CHARS 过滤器
定义和用法 FILTER_SANITIZE_SPECIAL_CHARS 过滤器对特殊字符进行 HTML 转义. 该过滤器用于转义 "<>& 以及 ASCII 值在 32 ...
- MySql中创建存储过程
MySQL 存储过程是从 MySQL 5.0 开始增加的新功能.存储过程的优点有一箩筐.不过最主要的还是执行效率和SQL 代码封装.特别是 SQL 代码封装功能,如果没有存储过程,在外部程序访问数据库 ...