dubbo同步调用、异步调用和是否返回结果源码分析和实例
0. dubbo同步调用、异步调用和是否返回结果配置
(1)dubbo默认为同步调用,并且有返回结果。
(2)dubbo异步调用配置,设置 async="true",异步调用可以提高效率。
(3)dubbo默认是有返回结果,不需要返回,可以设置return="false",不需要返回值,可以减少等待结果时间。
1. 源码分析(dubbo版本:2.6.0)
dubbo自身底层调用是使用netty异步实现的,默认同步调用返回结果,是通过获取ResponseFuture,然后使用ReentrantLock的await使当前线程等待结果,设置返回的。下面是部分核心代码部分:
com.alibaba.dubbo.rpc.protocol.dubbo.DubboInvoker.doInvoke(Invocation)
@Override
protected Result doInvoke(final Invocation invocation) throws Throwable {
RpcInvocation inv = (RpcInvocation) invocation;
final String methodName = RpcUtils.getMethodName(invocation);
inv.setAttachment(Constants.PATH_KEY, getUrl().getPath());
inv.setAttachment(Constants.VERSION_KEY, version); ExchangeClient currentClient;
if (clients.length == 1) {
currentClient = clients[0];
} else {
currentClient = clients[index.getAndIncrement() % clients.length];
}
try {
// 获取是否异步配置async
boolean isAsync = RpcUtils.isAsync(getUrl(), invocation);
// 获取是否需要返回结果配置return
boolean isOneway = RpcUtils.isOneway(getUrl(), invocation);
// 获取超时配置timeout
int timeout = getUrl().getMethodParameter(methodName, Constants.TIMEOUT_KEY, Constants.DEFAULT_TIMEOUT);
if (isOneway) {
// 不管是否异步,只要不需要返回结果,直接异步调用,设置结果为null
boolean isSent = getUrl().getMethodParameter(methodName, Constants.SENT_KEY, false);
currentClient.send(inv, isSent);
RpcContext.getContext().setFuture(null);
return new RpcResult();
} else if (isAsync) {
// 如果异步,并且需要返回结果,调用后设置结果future
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) {
throw new RpcException(RpcException.TIMEOUT_EXCEPTION, "Invoke remote method timeout. method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
} catch (RemotingException e) {
throw new RpcException(RpcException.NETWORK_EXCEPTION, "Failed to invoke remote method: " + invocation.getMethodName() + ", provider: " + getUrl() + ", cause: " + e.getMessage(), e);
}
}
2. 实例
这里使用dubbo源码自带的例子
(1)在dubbo-demo-api中定义异步服务
package com.alibaba.dubbo.demo;
public interface AsyncDemoService {
String sayHello(String name);
}
(2)在dubbo-demo-provider中实现
package com.alibaba.dubbo.demo.provider; import java.text.SimpleDateFormat;
import java.util.Date; import com.alibaba.dubbo.demo.AsyncDemoService;
import com.alibaba.dubbo.rpc.RpcContext; public class AsyncDemoServiceImpl implements AsyncDemoService{ @Override
public String sayHello(String name) {
System.out.println("[" + new SimpleDateFormat("HH:mm:ss").format(new Date()) + "] Hello " + name + ", request from consumer: " + RpcContext.getContext().getRemoteAddress());
return "Hello " + name + ", response form provider: " + RpcContext.getContext().getLocalAddress();
} }
(3)在dubbo-demo-provider.xml中配置服务信息
<bean id="asyncDemoService" class="com.alibaba.dubbo.demo.provider.AsyncDemoServiceImpl"/>
<dubbo:service interface="com.alibaba.dubbo.demo.AsyncDemoService" ref="asyncDemoService"/>
(4)在dubbo-demo-consumer.xml中配置调用服务信息,设置为异步调用async="true"
<dubbo:reference id="asyncDemoService" check="false" interface="com.alibaba.dubbo.demo.AsyncDemoService">
<dubbo:method name="sayHello" async="true"/>
</dubbo:reference>
(5)在dubbo-demo-consumer的Consumer类中增加调用
AsyncDemoService asyncDemoService = (AsyncDemoService) context.getBean("asyncDemoService");
asyncDemoService.sayHello("world");
// 通过 1.源码分析 中可以知道异步返回结果放到了RpcContext.getContext()中
Future<String> future = RpcContext.getContext().getFuture();
try {
String hello = future.get(1, TimeUnit.SECONDS);
System.out.println(hello);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
} catch (TimeoutException e) {
e.printStackTrace();
}
(6)不需要返回结果,配置dubbo-demo-consumer.xml 中return="false",同步异步的调用方式一样的,很简单,只需要调用一下就可以继续其他操作,下面是异步的例子。
AsyncDemoService asyncDemoService = (AsyncDemoService) context.getBean("asyncDemoService");
asyncDemoService.sayHello("world");
dubbo同步调用、异步调用和是否返回结果源码分析和实例的更多相关文章
- 【转载】Android异步消息处理机制详解及源码分析
PS一句:最终还是选择CSDN来整理发表这几年的知识点,该文章平行迁移到CSDN.因为CSDN也支持MarkDown语法了,牛逼啊! [工匠若水 http://blog.csdn.net/yanbob ...
- dubbo注册服务IP解析异常及IP解析源码分析
在使用dubbo注册服务时会遇到IP解析错误导致无法正常访问. 比如: 本机设置的IP为172.16.11.111, 但实际解析出来的是180.20.174.11 这样就导致这个Service永远也无 ...
- Android进阶——多线程系列之异步任务AsyncTask的使用与源码分析
AsyncTask是一种轻量级的异步任务类,它可以在线程池中执行后台任务,然后把执行的进度和最终结果传递给主线程并主线程中更新UI,通过AsyncTask可以更加方便执行后台任务以及在主线程中访问UI ...
- dubbo负载均衡策略及对应源码分析
在集群负载均衡时,Dubbo 提供了多种均衡策略,缺省为 random 随机调用.我们还可以扩展自己的负责均衡策略,前提是你已经从一个小白变成了大牛,嘻嘻 1.Random LoadBalance 1 ...
- 源码分析Dubbo服务消费端启动流程
通过前面文章详解,我们知道Dubbo服务消费者标签dubbo:reference最终会在Spring容器中创建一个对应的ReferenceBean实例,而ReferenceBean实现了Spring生 ...
- C# 委托的三种调用示例(同步调用 异步调用 异步回调)
首先,通过代码定义一个委托和下面三个示例将要调用的方法: 复制代码 代码如下: public delegate int AddHandler(int a,int b); public class ...
- python 37 同步、异步调用
目录 1. 阻塞与非阻塞 2. 同步与异步 2.1 异步调用 2.2 同步调用 2.3 异步调用回收的第一种方式 3. 异步调用+回调函数 3.1 requests模块 3.2 异步调用回收的第二种方 ...
- 20160711--C# 委托的三种调用示例(同步调用 异步调用 异步回调)【转载】
首先,通过代码定义一个委托和下面三个示例将要调用的方法: 代码如下: public delegate int AddHandler(int a,int b); public class 加法类 { p ...
- 浅谈WebService开发二(同步与异步调用)转
上文 <http://www.dotnetgeek.cn/xuexiwebservice1.html>已经跟大家说了,如果创建一个webservice和简单的调用,本文将注重webserv ...
随机推荐
- MySQL8.0 DDL原子性特性
1. DDL原子性概述 8.0之前并没有统一的数据字典dd,server层和引擎层各有一套元数据,sever层的元数据包括(.frm,.opt,.par,.trg等),用于存储表定义,分区表定义,触发 ...
- React躬行记(4)——生命周期
组件的生命周期(Life Cycle)包含三个阶段:挂载(Mounting).更新(Updating)和卸载(Unmounting),在每个阶段都会有相应的回调方法(也叫钩子)可供选择,从而能更好的控 ...
- GIS热力图制作与位置大数据分析
最近有很多朋友咨询位置数据.热力图等等东西,我一一进行了解答,但是个人精力实在有限,特写一个博客进行详细技术说明,其实这个东西位置数据.百度地图POI.高德地图POI等数据爬取.存储都较为简单,热力图 ...
- Storm 学习之路(一)—— Storm和流处理简介
一.Storm 1.1 简介 Storm 是一个开源的分布式实时计算框架,可以以简单.可靠的方式进行大数据流的处理.通常用于实时分析,在线机器学习.持续计算.分布式RPC.ETL等场景.Storm具有 ...
- 怎么安装IDEA?
我们使用的是的2017.3.4版本: 然后弹出激活窗口 破解方法: 1.下载破解插件JetbrainsCrack-2.7-release-str.jar 2.把插件放到安装目录下的bin文件夹下 3. ...
- 苹果二代TWS无线耳机AirPods调研
产品介绍 苹果AirPods二代自从2018年9月份上市以来,到现在将近一年的时间了,据江湖传闻,苹果AirPods的总售卖个数,已经超过了5000W部,这样价格的TWS耳机,能够卖那么多的量,估计也 ...
- gmap 获取瓦片数
在 gmap1.7版本中 gMapControl1.MapProvider.Projection.GetAreaTileCount(area, i, 0); 可用来获取到erea里i层的瓦片数量. 但 ...
- 搭建minima主题的github博客网站
layout: post title: "搭建minima主题的github博客网站" date: 2019-04-20 19:20:20 +0800 --- 作者:吴甜甜 个人博 ...
- C# 位运算及实例计算
前言: 平时在实际工作中很少用到这个,虽然都是一些比较基础的东西,但一旦遇到了,又不知所云.刚好最近接触了一些相关这方面的项目,所以也算是对 这些内容重新温习实践了一遍.所以这篇不仅作为个人备忘,也分 ...
- 解决 Prometheus 不能获取 Kubernetes 集群上 Windows 节点的 Metrics
背景 接上一篇 快速搭建 Windows Kubernetes , 我们发现原来在 Windows Kubernetes 会有一些与在 Linux 上使用不一样的体验,俗称坑,例如 hostAlias ...