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 异步回调的更多相关文章

  1. 抓到Dubbo异步调用的小BUG,再送你一个贡献开源代码的机会

    hello,大家好呀,我是小楼. 最近一个技术群有同学at我,问我是否熟悉Dubbo,这我熟啊~ 他说遇到了一个Dubbo异步调用的问题,怀疑是个BUG,提到BUG我可就不困了,说不定可以水,哦不.. ...

  2. node 异步回调解决方法之yield

    先看如何使用 使用的npm包为genny,npm 安装genny,使用 node -harmony 文件(-harmony 为使用es6属性启动参数) 启动项目 var genny= require( ...

  3. c#线程之异步委托begininvoke、invoke、AsyncWaitHandle.WaitOne 、异步回调

    单靠自己看书学总是会走很多弯路,任何人也不列外,有些时候自己遇到的很多问题,其它别人在很久之前也可能遇到过,上网查查可以走很大捷径,对自己的学习有很大帮助,刚开始弄线程这块,一开始只是看书,很多东西都 ...

  4. Android异步回调中的UI同步性问题

    Android程序编码过程中,回调无处不在.从最常见的Activity生命周期回调开始,到BroadcastReceiver.Service以及Sqlite等.Activity.BroadcastRe ...

  5. java 中的异步回调

    异步回调,本来在c#中是一件极为简单和优雅的事情,想不到在java的世界里,却如此烦琐,先看下类图: 先定义了一个CallBackTask,做为外层的面子工程,其主要工作为start 开始一个异步操作 ...

  6. C“中断” 与 JS“异步回调” 横向对比

    在底层C语言中,有一个非常重要而特别的概念,叫做“中断”.用比喻来说,我正在写着博客,突然我妈打个电话过来,我就离开了键盘去接电话了,然后写博客就中断了,我聊完电话回来再继续写.乍一听似乎并没有什么大 ...

  7. State Threads——异步回调的线性实现

    State Threads——异步回调的线性实现 原文链接:http://coolshell.cn/articles/12012.html 本文的标题看起来有点拗口,其实State Threads库就 ...

  8. 委托(delegate)的三种调用方式:同步调用,异步调用,异步回调(转载)

    下面为即将被调用的方法: public delegate int AddHandler(int a,int b); public class 加法类 { public static int Add(i ...

  9. 协程 & 用户级(内核级)线程 & 切换开销 & 协程与异步回调的差异

    今天先是看到多线程级别的内容,然后又看到协程的内容. 基本的领会是,协程是对异步回调方式的一种变换,同样是在一个线程内,协程通过主动放弃时间片交由其他协程执行来协作,故名协程. 而协程很早就有了,那时 ...

随机推荐

  1. final、finally、finalize区别

    final final关键字可以用来修饰类,方法以及成员变量,当用在不同的场景下时具有不同的意义. 修饰类 如果修饰类,则代表这个类不可继承 修饰方法 如果修饰方法,则代表这个方法不可覆写:同时,允许 ...

  2. [js]浏览器同源策略(same-origin policy)

    浏览器的同源策略 浏览器同源政策及其规避方法 什么是同源策略 A网页设置的 Cookie,B网页不能打开,除非这两个网页"同源".所谓"同源"指的是" ...

  3. python+requests+excel+unittest+ddt接口自动化数据驱动并生成html报告(二)

    可以参考 python+requests接口自动化完整项目设计源码(一)https://www.cnblogs.com/111testing/p/9612671.html 原文地址https://ww ...

  4. Creator仿超级玛丽小游戏源码分享

    Creator仿超级玛丽小游戏源码分享 之前用Cocos Creator 做的一款仿超级玛丽的游戏,使用的版本为14.2 ,可以直接打包为APK,现在毕设已经完成,游戏分享出来,大家一起学习进步.特别 ...

  5. 027-Session状态提供程序

    Session分三种:1.InProc(进程内)-默认就是这种-速度快/但内存小/易丢失进程外:可以在IIS或ASPNET服务意外关闭时继续保持状态,注意此时存储到session中的对象必须支持序列化 ...

  6. 抓包工具 GOOGLE

    chrome://net-internals/#events GOOGLE浏览器直接输入

  7. maven ${path.separator}

    ${path.separator} 兼容 windows & linux: <compilerArguments> <verbose /> <bootclassp ...

  8. 专题8:javascript中事件

    一.事件流 1.1 事件冒泡 冒泡型事件:事件按照从最特定的事件目标到最不特定的事件目标的顺序逐一触发: 注意:各个浏览器在处理<html>标记级别的事件时顺序有出入,因此无论任何情况,都 ...

  9. HTTP请求中POST与GET的区别

      本文章已收录于:   一.原理区别 一般我们在浏览器输入一个网址访问网站都是GET请求;再FORM表单中,可以通过设置Method指定提交方式为GET或者POST提交方式,默认为GET提交方式. ...

  10. Vertical viewport was given unbounded height

    new Expanded( child: new ListView( ..... ) ); +++++++++++++++ 可以通过指定shrinkWrap = true为了你ListView. Li ...