dubbo 异步回调
dubbo 异步回调的使用
业务接口:
public interface HelloService {
String sayHello();
void sayHi(String name);
}
回调服务类:
public class CbService {
// onreturn 函数的参数是有限定的,细节下面提及。
public void onreturn(String str) {
System.out.println("onreturn:" + str);
}
public void onthrow(Throwable ex) {
System.out.println("onthrow");
}
public String oninvoke() {
System.out.println("oninvoke");
return null;
}
}
xml 配置:(oninvoke 暂时没有配置好)
<bean id="cbService" class="com.zhang.CbService"></bean>
<dubbo:reference id="hello"
loadbalance="roundrobin" check="false" interface="com.zhang.HelloService" >
<dubbo:method name="sayHello"
async="true"
onreturn="cbService.onreturn"
onthrow="cbService.onthrow">
</dubbo:method>
</dubbo:reference>
1. 异步回调的源头从 FutureFilter 发起,这是一个 consumer 端的 filter,它为 Future 设置回调函数。
@Activate(group = Constants.CONSUMER)
public class FutureFilter implements Filter { public Result invoke(final Invoker<?> invoker, final Invocation invocation) throws RpcException {
final boolean isAsync = RpcUtils.isAsync(invoker.getUrl(), invocation); fireInvokeCallback(invoker, invocation);
// 发起调用请求
Result result = invoker.invoke(invocation); if (isAsync) {
// 注册异步回调函数
asyncCallback(invoker, invocation);
} else {
syncCallback(invoker, invocation, result);
}
return result;
} // 为 Future 设置 callback
private void asyncCallback(final Invoker<?> invoker, final Invocation invocation) {
Future<?> f = RpcContext.getContext().getFuture();
if (f instanceof FutureAdapter) {
ResponseFuture future = ((FutureAdapter<?>)f).getFuture();
future.setCallback(new ResponseCallback() {
public void done(Object rpcResult) {
if (rpcResult == null){
logger.error(new IllegalStateException("invalid result value : null, expected "+Result.class.getName()));
return;
}
///must be rpcResult
if (! (rpcResult instanceof Result)){
logger.error(new IllegalStateException("invalid result type :" + rpcResult.getClass() + ", expected "+Result.class.getName()));
return;
}
Result result = (Result) rpcResult;
if (result.hasException()) {
fireThrowCallback(invoker, invocation, result.getException());
} else {
fireReturnCallback(invoker, invocation, result.getValue());
}
}
public void caught(Throwable exception) {
fireThrowCallback(invoker, invocation, exception);
}
});
}
} private void fireReturnCallback(final Invoker<?> invoker, final Invocation invocation, final Object result) {
final Method onReturnMethod = (Method)StaticContext.getSystemContext().get(StaticContext.getKey(invoker.getUrl(), invocation.getMethodName(), Constants.ON_RETURN_METHOD_KEY));
final Object onReturnInst = StaticContext.getSystemContext().get(StaticContext.getKey(invoker.getUrl(), invocation.getMethodName(), Constants.ON_RETURN_INSTANCE_KEY)); //not set onreturn callback
if (onReturnMethod == null && onReturnInst == null ){
return ;
} if (onReturnMethod == null || onReturnInst == null ){
throw new IllegalStateException("service:" + invoker.getUrl().getServiceKey() +" has a onreturn callback config , but no such "+(onReturnMethod == null ? "method" : "instance")+" found. url:"+invoker.getUrl());
}
if (onReturnMethod != null && ! onReturnMethod.isAccessible()) {
onReturnMethod.setAccessible(true);
} Object[] args = invocation.getArguments();
Object[] params ;
Class<?>[] rParaTypes = onReturnMethod.getParameterTypes() ;
if (rParaTypes.length >1 ) {
if (rParaTypes.length == 2 && rParaTypes[1].isAssignableFrom(Object[].class)){
params = new Object[2];
params[0] = result;
params[1] = args ;
}else {
params = new Object[args.length + 1];
params[0] = result;
System.arraycopy(args, 0, params, 1, args.length);
}
} else {
params = new Object[] { result };
}
// 经过前面的 if else 后,必定有 params[0] = result;
// result 是 RpcResult 的 value,即 provider 接口的返回值。
// 所以,CbService 的 onreturn 函数的第一个参数必须是接口的返回值。
try {
onReturnMethod.invoke(onReturnInst, params);
} catch (InvocationTargetException e) {
fireThrowCallback(invoker, invocation, e.getTargetException());
} catch (Throwable e) {
fireThrowCallback(invoker, invocation, e);
}
}
}
2. 当 consumer 收到服务端的响应时,触发回调函数,调用栈如下:
dubbo 异步回调的更多相关文章
- 抓到Dubbo异步调用的小BUG,再送你一个贡献开源代码的机会
hello,大家好呀,我是小楼. 最近一个技术群有同学at我,问我是否熟悉Dubbo,这我熟啊~ 他说遇到了一个Dubbo异步调用的问题,怀疑是个BUG,提到BUG我可就不困了,说不定可以水,哦不.. ...
- node 异步回调解决方法之yield
先看如何使用 使用的npm包为genny,npm 安装genny,使用 node -harmony 文件(-harmony 为使用es6属性启动参数) 启动项目 var genny= require( ...
- c#线程之异步委托begininvoke、invoke、AsyncWaitHandle.WaitOne 、异步回调
单靠自己看书学总是会走很多弯路,任何人也不列外,有些时候自己遇到的很多问题,其它别人在很久之前也可能遇到过,上网查查可以走很大捷径,对自己的学习有很大帮助,刚开始弄线程这块,一开始只是看书,很多东西都 ...
- Android异步回调中的UI同步性问题
Android程序编码过程中,回调无处不在.从最常见的Activity生命周期回调开始,到BroadcastReceiver.Service以及Sqlite等.Activity.BroadcastRe ...
- java 中的异步回调
异步回调,本来在c#中是一件极为简单和优雅的事情,想不到在java的世界里,却如此烦琐,先看下类图: 先定义了一个CallBackTask,做为外层的面子工程,其主要工作为start 开始一个异步操作 ...
- C“中断” 与 JS“异步回调” 横向对比
在底层C语言中,有一个非常重要而特别的概念,叫做“中断”.用比喻来说,我正在写着博客,突然我妈打个电话过来,我就离开了键盘去接电话了,然后写博客就中断了,我聊完电话回来再继续写.乍一听似乎并没有什么大 ...
- State Threads——异步回调的线性实现
State Threads——异步回调的线性实现 原文链接:http://coolshell.cn/articles/12012.html 本文的标题看起来有点拗口,其实State Threads库就 ...
- 委托(delegate)的三种调用方式:同步调用,异步调用,异步回调(转载)
下面为即将被调用的方法: public delegate int AddHandler(int a,int b); public class 加法类 { public static int Add(i ...
- 协程 & 用户级(内核级)线程 & 切换开销 & 协程与异步回调的差异
今天先是看到多线程级别的内容,然后又看到协程的内容. 基本的领会是,协程是对异步回调方式的一种变换,同样是在一个线程内,协程通过主动放弃时间片交由其他协程执行来协作,故名协程. 而协程很早就有了,那时 ...
随机推荐
- java框架之Quartz-任务调度&整合Spring
准备 介绍 定时任务,无论是互联网公司还是传统的软件行业都是必不可少的.Quartz,它是好多优秀的定时任务开源框架的基础,使用它,我们可以使用最简单基础的配置来轻松的使用定时任务. Quartz 是 ...
- java之IDEA中使用Maven
Maven的安装与使用 安装 1.下载,官网下载. 2.解压,存放路径中不可包含空格和中文.如:"E:\dev\workspace\maven\apache-maven-3.6.0" ...
- sap 软件架构
1:
- spring datasource 使用 proxool
XmlWebApplicationContext使用的xml配置如下: <?xml version="1.0" encoding="UTF-8"?> ...
- PSPnet模型结构的实现代码
1 import torch import torch.nn.functional as F from torch import nn from torchvision import models f ...
- html5 javascript 事件练习3键盘控制练习
<!DOCTYPE html><html lang="en"><head> <meta charset="UTF-8&qu ...
- 使用java进行 AES 加密 解密?
百度百科是这样定义的: 高级加密标准(英语:Advanced Encryption Standard,缩写:AES),在密码学中又称Rijndael加密法,是美国联邦政府采用的一种区块加密标准.这个标 ...
- 鼠标右键vsCode打开
有时候在安装vscode不会出现鼠标右键用vscode打开的情况: 最终要实现的样子: 解决办法如下步骤: 1.安装vscode: 2.新建一个“.reg”为后缀的文件: 3.把下面内容复制到文件中: ...
- LNMP 如何安装mongodb
wget -c http://fastdl.mongodb.org/linux/mongodb-linux-x86_64-2.6.4.tgztar -zxvf mongodb-linux-x86_64 ...
- keepalived + lvs
Keepalived原理 Keepalived原理 keepalived也是模块化设计,不同模块复杂不同的功能,下面是keepalived的组件 core check vrrp libipfwc li ...