dubbo 请求调用过程分析
服务消费方发起请求
当服务的消费方引用了某远程服务,服务的应用方在spring的配置实例如下:
<dubbo:referenceid="demoService"interface="com.alibaba.dubbo.demo.DemoServ ice" />
demoService实例其实是代理工厂生产的代理对象(大家可以参考代理那部分生成的伪代码),在代码中调用demoService.sayHello(“world!”)时,
1. 将方法名方法参数传入InvokerInvocationHandler的invoke方
对于Object中的方法toString, hashCode, equals直接调用invoker的对应方法,
这里对于Object的方法需要被远程调用吗?调用了是不是报错比默认处理更好呢??
远程调用层是以Invocation, Result为中心, 这里根据要调用的方法以及传入的参数构建RpcInvocation对象,作为Invoker的入参
2. MockClusterInvoker根据参数提供了三种调用策略
不需要mock, 直接调用FailoverClusterInvoker
强制mock,调用mock
先调FailoverClusterInvoker,调用失败在mock、
3. FailoverClusterInvoker默认调用策略
通过目录服务查找到所有订阅的服务提供者的Invoker对象
路由服务根据策略来过滤选择调用的Invokers
通过负载均衡策略LoadBalance来选择一个Invoker
4. 执行选择的Invoker.inoker(invocation)
经过监听器链,默认没有
经过过滤器链,内置实现了很多
执行到远程调用的DubboInvoker
5. DubboInvoker
根据url 也就是根据服务提供者的长连接,这里封装成交互层对象ExchangeClient供这里调用
判断远程调用类型同步,异步还是oneway模式
ExchangeClient发起远程调用,底层remoting不在这里描述了
获取调用结果:
Oneway返回空RpcResult
异步,直接返回空RpcResult, ResponseFuture回调
同步, ResponseFuture模式同步转异步,等待响应返回
服务提供方接收调用请求
同样我们也是rpc调用层DubboProtocol层开始分析,对于通信层remoting的数据接收反序列等等过程不做分析。
DubboProtocol的requestHandler是ExchangeHandler的实现,是remoting层接收数据后的回调。
requestHandler.replay方法接收请求消息,这里只处理远程调用消息Invocation。
1. 通过Invocation获取服务名和端口组成serviceKey=com.alibaba.dubbo.demo.DemoService:20880, 从DubboProtocol的exproterMap中获取暴露服务的DubboExporter, 在从dubboExporter 获取invoker返回
2. 经过过滤器链
3. 经过监听器链
4. 到达执行真正调用的invoker, 这个invoker由代理工厂ProxyFactory.getInvoker(demoService, DemoService.class, registryUrl)创建,具体请看代理那部分介绍。
调用demoService实例方法,将结果封装成RpcResult返回
5. 交换层构建Response,通过Remoting层编码传输将结果响应给调用方
服务消费方发起远程调用的底层通信
服务提供方接收请求并响应的底层通信
一:provider提供方
ClassPathXmlApplicationContext <init>(构造方法)
-> ClassPathXmlApplicationContext refresh()
-> ClassPathXmlApplicationContext finishRefresh()
-> AbstractApplicationContext publishEvent()
-> ServiceBean onApplicationEvent()
-> ServiceConfig doExport()
#构造dubbo对象 application provider module protocol registry service reference consume等
-> ServiceConfig doExportUrls #导出URL,获取注册中心RegistryConfig
#注册中心:registry://10.199.101.228:2181/com.alibaba.dubbo.registry.RegistryService?application=demo&backup=10.199.101.227:2181,10.199.101.229:2181&dubbo=2.4.9&pid=8045®istry=zookeeper×tamp=1491546077803
-> ServiceConfig doExportUrlsFor1Protocol()
#需要暴露 dubbo://10.199.66.242:20880/com.unj.dubbotest.provider.DemoService?anyhost=true&application=dubbo_demo_provider&dubbo=2.4.9&interface=com.unj.dubbotest.provider.DemoService&methods=sayHello,getUsers&pid=8045&revision=0.0.1&side=provider×tamp=1491546674441&version=0.0.1
-> ServiceConfig exportLocal()
-> Exporter<?> exporter = protocol.export(proxyFactory.getInvoker(ref, (Class) interfaceClass, local));
#暴露Invoker<XxxService>调用服务代理类
-> proxyFactory.getInvoker(ref, (Class) interfaceClass, local)
#返回 AbstractProxyInvoker代理ProxyInvoker<XxxService>
public abstract class AbstractProxyInvoker<T> implements Invoker<T> {
private final T proxy; //代理目标实例 XxxServiceImpl
private final Class<T> type;
private final URL url;
}
-> InvokerInvocationHandler.invoke()
#invoker.invoke(new RpcInvocation(method, args)).recreate();
-> DubboProtocol export(Invoker<T> invoker)
# 返回暴露Exporter<T>
public class DubboExporter<T> extends AbstractExporter<T> {
private final String key; //com.unj.dubbotest.provider.DemoService:0.0.1:20880
private final Map<String, Exporter<?>> exporterMap;
public DubboExporter(Invoker<T> invoker, String key, Map<String, Exporter<?>> exporterMap){
super(invoker);
this.key = key;
this.exporterMap = exporterMap;
}
-> DubboProtocol openServer(url)
#url dubbo://10.199.66.242:20880/com.unj.dubbotest.provider.DemoService?anyhost=true&application=dubbo_demo&dubbo=2.4.9&interface=com.unj.dubbotest.provider.DemoService&methods=sayHello,getUsers&pid=8045&revision=0.0.1&side=provider×tamp=1491546674441&version=0.0.
#serverMap.put(key, createServer(url)); key:10.199.66.242:20880 value:ExchangeServer
-> DubboProtocol createServer(URL url)
#返回HeaderExchangeServer,添加参数列表 如心跳,心跳时间
-> Exchangers.bind(url, requestHandler);
#返回HeaderExchangeServer,getTransporter()获取的实例来源于配置,默认返回一个NettyTransporter
-> HeaderExchangeServer.bind(URL url, ExchangeHandler handler);
-> HeaderExchangeServer(Transporters.bind(url, new DecodeHandler(new HeaderExchangeHandler(handler))));
#HeaderExchangeServer包装实例NettyServer
-> NettyTransporter.bind(URL url, ChannelHandler listener)
#return new NettyServer(url, listener)
-> NettyServer.doOpen();
#打开socket监听端口准备接收消息
#ServerBootstrap bind(getBindAddress())绑定地址端口
#RpcInvocation 具体类名、方法名、调用参数
#DubboInvoker – 执行具体的远程调用,包含初始化信息如client
#Protocol – 服务地址的发布和订阅
#Exporter – 暴露服务的引用,或取消暴露
二:consume(消费方):
->ReferenceConfig.init
#consume端启动初始化
->DubboProtocol.refer
#根据参数url,接口等构建Invoker
->JavassistProxyFactory.getProxy(Invoker<T> invoker, Class<?>[] interfaces)
#构建代理对象Proxy.getProxy(interfaces).newInstance(new InvokerInvocationHandler(invoker));
->DemoService.say(String hello);#真正调用时候
->InvokerInvocationHandler.invoke(Object proxy, Method method, Object[] args)
#invoker.invoke(new RpcInvocation(method, args)).recreate();RpcInvocation包装参数方法名
->DubboInvoker.doInovke(final Invocation invocation)
#统一代理调用
->ExchangeClient.send(invocation, isSent);
->HeaderExchangeChannel.request(Object request, int timeout)
->NettyChannel.send(Object message, boolean sent)
三:dubbo 底层通讯:NettyClient <-- 异步NIO传输 socket监听-> NettyServer
四:consume --> provider 调用过程:
-> NettyServer->NettyHandler.messageReceived #接收消息处理器
-> MultiMessageHandler->HeartbeatHandler->AllChannelHandler->DecodeHandler->HeaderExchangeHandler->DubboProtocol$requestHandler
#NettyServer启动时候绑定MultiMessageHandler
#DubboProtocol.getServers() 检索serverMap获取Exporter<?>
#DubboProtocol.getServers() 检索serverMap获取ExchangeServer
-> ExchangeHandlerAdapter.reply
#真正获取Invoker,将传入message 转换 invocation
-> invoker.invoke(invocation)
-> JavassistProxyFactory$AbstractProxyInvoker.doInvoke
#服务端Invoker代理 AbstractProxyInvoker调用目标引用service,客户端DubboInvoker
参考更多免费教程请加入Dubbo技术交流:548209960
dubbo 请求调用过程分析的更多相关文章
- dubbo+zipkin调用链监控(二)
*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...
- 9.4 dubbo异步调用原理
9.1 客户端发起请求源码.9.2 服务端接收请求消息并发送响应消息源码.9.3 客户端接收响应信息(异步转同步的实现) 分析了dubbo同步调用的源码,现在来看一下dubbo异步调用. 一.使用方式 ...
- 限时购校验小工具&dubbo异步调用实现限
本文来自网易云社区 作者:张伟 背景 限时购是网易考拉目前比较常用的促销形式,但是前期创建一个限时购活动时需要各个BU按照指定的Excel格式进行选品提报,为了保证提报数据准确,运营需要人肉校验很多信 ...
- Spring Cloud Feign 调用过程分析
前面已经学习了两个Spring Cloud 组件: Eureka:实现服务注册功能: Ribbon:提供基于RestTemplate的HTTP客户端并且支持服务负载均衡功能. 通过这两个组件我们暂时可 ...
- Dubbo服务调用过程源码解析④
目录 0.服务的调用 1.发送请求 2.请求编码 3.请求的解码 4.调用具体服务 5.返回调用结果 6.接收调用结果 Dubbo SPI源码解析① Dubbo服务暴露源码解析② Dubbo服务引用源 ...
- dubbo系列二、dubbo请求流程记录
目录 1.dubbo请求处理流程 1.1. consumer端处理流程 1.2.provider端处理流程 1.3.dubbo请求分析记录-图 泳道图 xmind图 2.dubbo请求核心说明 1.d ...
- 抓到Dubbo异步调用的小BUG,再送你一个贡献开源代码的机会
hello,大家好呀,我是小楼. 最近一个技术群有同学at我,问我是否熟悉Dubbo,这我熟啊~ 他说遇到了一个Dubbo异步调用的问题,怀疑是个BUG,提到BUG我可就不困了,说不定可以水,哦不.. ...
- Post方式的Http流请求调用
HttpRequest公共类: public static class HttpRequestAction { /// <summary> /// 发送http请求并返回响应 /// &l ...
- Dubbo服务调用的动态代理和负载均衡
Dubbo服务调用的动态代理及负载均衡源码解析请参见:http://manzhizhen.iteye.com/blog/2314514
随机推荐
- WPF报表自定义通用可筛选列头-WPF特工队内部资料
由于项目需要制作一个可通用的报表多行标题,且可实现各种类型的内容显示,包括文本.输入框.下拉框.多选框等(自定的显示内容可自行扩展),并支持参数绑定转换,效果如下: 源码结构 ColumnItem类: ...
- 微软Build 2017第二天 .NET Standard 2.0 Preview 的客户端跨平台
微软公司一年一度的开发者大会,即“Microsoft Build 2017”在总部西雅图正式开幕.按照官方安排,本次大会将持续 3 天,主题围绕微软公司各项最新技术成果的展示和研讨,包括与微软相关的产 ...
- 手机共享成wifi热点电脑无法上网的问题
第二次遇到这样的问题,每次百度都不能解决我遇到的问题.上一次已经自己鼓捣着解决了,后来忘记怎么弄好的.第二次遇到这个问题,又是浪费了许多时间后,偶然弄好了,突然想起来上次就是这样弄好的.所以就针对我自 ...
- 关于Ubuntu的ssh免密登录
1.打开"终端窗口",输入"sudo apt-get update"-->回车-->"输入当前登录用户的管理员密码"--> ...
- 使用Redis实现分布式锁
在天猫.京东.苏宁等等电商网站上有很多秒杀活动,例如在某一个时刻抢购一个原价1999现在秒杀价只要999的手机时,会迎来一个用户请求的高峰期,可能会有几十万几百万的并发量,来抢这个手机,在高并发的情形 ...
- JDBC事务详解
在JDBC的数据库操作中,事务是由一个或者多个操作组成的一个不可分割的工作单元.JDBC的事务处理包含三个方面:事务的自动提交模式(Auto-commit mode).事务隔离级别(Transacti ...
- .Net程序员学用Oracle系列(7):视图、函数、存储过程、包
1.视图 1.1.创建.删除及调用普通视图 1.2.高级视图介绍 2.函数 2.1.系统函数介绍 2.2.创建.删除及调用自定义函数 3.存储过程 3.1.创建.修改及删除存储过程 3.2.调用存储过 ...
- 【shell脚本实例】一个恶作剧—— kill掉占用CPU较高的matlab进程
我们实验室有台服务器,博士们在服务器上跑MATLAB,基本都是4核都是超过95%的CPU占用,想了个恶作剧的shell 定时kill掉MATLAB程序,是不是很邪恶啊,哈哈~~~ 不过我只是干过一次 ...
- 并串转换FPGA电路结构的探讨
如题,并串转换时FPGA设计里,一个很常用的模块,这里有一个小的探讨. 一般情况下我们可以使用一个计数器与数据选择器进行并串转换,如下图的的结构.这个结构通过计数器不断的改变数据选择器的地址端,从而使 ...
- 5.Lock接口及其实现ReentrantLock
jdk1.7.0_79 在java.util.concurrent.locks这个包中定义了和synchronized不一样的锁,重入锁——ReentrantLock,读写锁——ReadWriteLo ...