dubbo请求调用过程分析

服务消费方发起请求

 

当服务的消费方引用了某远程服务,服务的应用方在spring的配置实例如下:

 

<dubbo:reference id="demoService" interface="com.alibaba.dubbo.demo.DemoService" />

 

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&registry=zookeeper&timestamp=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&timestamp=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&timestamp=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

原文链接:[http://wely.iteye.com/blog/2378164]

时间: 2024-08-03 19:29:07

dubbo请求调用过程分析的相关文章

爬取 html js java-大神啊!如何用HTTP请求调用网页中的脚本啊!神er

问题描述 大神啊!如何用HTTP请求调用网页中的脚本啊!神er 大神们,我现在想做一个东西,就是要在百度网盘上下载东西,手动下载的时候要点击两个按钮,我用程序怎么实现这两次点击呢?应该向着哪个方向解决这个问题呢,神er. 我看了下html代码,里面是调用的JS,JS又调用了别的什么玩意,这个是点击第一个按钮的click触发代码,第二个按钮在静态的HTML上找不到啊,神啊,出来吧!! function(B){ var A=disk.util.ViewShareUtils.viewShareData

详解Android的OkHttp包编写异步HTTP请求调用的方法_Android

OkHttp 除了支持常用的同步 HTTP 请求之外,还支持异步 HTTP 请求调用.在使用同步调用时,当前线程会被阻塞,直到 HTTP 请求完成.当同时发出多个 HTTP 请求时,同步调用的性能会比较差.这个时候通过异步调用可以提高整体的性能. 在通过 newCall 方法创建一个新的 Call 对象之后,不是通过 execute 方法来同步执行,而是通过 enqueue 方法来添加到执行队列中.在调用 enqueue 方法时需要提供一个 Callback 接口的实现.在 Callback 接

详解Android的OkHttp包编写异步HTTP请求调用的方法

OkHttp 除了支持常用的同步 HTTP 请求之外,还支持异步 HTTP 请求调用.在使用同步调用时,当前线程会被阻塞,直到 HTTP 请求完成.当同时发出多个 HTTP 请求时,同步调用的性能会比较差.这个时候通过异步调用可以提高整体的性能. 在通过 newCall 方法创建一个新的 Call 对象之后,不是通过 execute 方法来同步执行,而是通过 enqueue 方法来添加到执行队列中.在调用 enqueue 方法时需要提供一个 Callback 接口的实现.在 Callback 接

架构师之路-在Dubbo中开发REST风格的远程调用

概述 dubbo支持多种远程调用方式,例如dubbo RPC(二进制序列化 + tcp协议).http invoker(二进制序列化 + http协议,至少在开源版本没发现对文本序列化的支持).hessian(二进制序列化 + http协议).WebServices (文本序列化 + http协议)等等,但缺乏对当今特别流行的REST风格远程调用(文本序列化 + http协议)的支持. 有鉴于此,我们基于标准的Java REST API--JAX-RS 2.0(Java API for REST

php-PHP怎么请求soap。其中要调用的那个方法的参数是这个方法的对象参数。到底该怎么调用

问题描述 PHP怎么请求soap.其中要调用的那个方法的参数是这个方法的对象参数.到底该怎么调用 且我用__getFunctions获取到要调用的方法是PayResponse Pay(Pay $parameters).我试了好几次都报错,报:Object reference not set to an instance of an objec.请问该PayResponse Pay(Pay $parameters)方法怎么用PHP的soap请求调用.希望详细点. 解决方案 用httprequest

Dubbo超时和重连机制

dubbo启动时默认有重试机制和超时机制. 超时机制的规则是如果在一定的时间内,provider没有返回,则认为本次调用失败, 重试机制在出现调用失败时,会再次调用.如果在配置的调用次数内都失败,则认为此次请求异常,抛出异常. 如果出现超时,通常是业务处理太慢,可在服务提供方执行:jstack PID > jstack.log 分析线程都卡在哪个方法调用上,这里就是慢的原因.如果不能调优性能,请将timeout设大. 某些业务场景下,如果不注意配置超时和重试,可能会引起一些异常. 超时设置 DU

基于Dubbo框架构建分布式服务

Dubbo是Alibaba开源的分布式服务框架,我们可以非常容易地通过Dubbo来构建分布式服务,并根据自己实际业务应用场景来选择合适的集群容错模式,这个对于很多应用都是迫切希望的,只需要通过简单的配置就能够实现分布式服务调用,也就是说服务提供方(Provider)发布的服务可以天然就是集群服务,比如,在实时性要求很高的应用场景下,可能希望来自消费方(Consumer)的调用响应时间最短,只需要选择Dubbo的Forking Cluster模式配置,就可以对一个调用请求并行发送到多台对等的提供方

程超:手把手教你动手扩展分布式调用链

一.说在前面 微服务是当下最火的词语,现在很多公司都在推广微服务,当服务越来越多的时候,我们是否会纠结以下几个问题: 面对一笔超时的订单,究竟是哪一步处理时间超长呢? 数据由于并发莫名篡改,到底都谁有重大嫌疑呢? 处理遗漏了一笔订单,曾经是哪个环节出错把它落下了? 系统莫名的报错,究竟是哪一个服务报的错误? 每个服务那么多实例服务器,如何快速定位到是哪一个实例服务器报错的呢? 现在很多系统都要求可用性达到99.9%以上,那么我们除了增加系统健壮性减少故障的同时,我们又如何在真正发生故障的时候,快

编码实现Spring Cloud微服务负载均衡调用(eureka、ribbon)

Spring 封装.揉和了一批开源项目,其中以Netflix开源的为主,比如zuul.eureka.hystrix.robbin等:然后就有了现在的Spring cloud微服务架构.这也充分展现了Spring的揉合能力. Spring cloud通过封装使这些项目融入spring的bean管理机制中,从而方便使用.这套微服务的核心功能还是使用这些项目的. 由本篇的标题可以想到本篇就是不使用Spring的注解和配置来使用这套微服务.看看现在网上关于Spring cloud的示例,千篇一律那几行注