码迷,mamicode.com
首页 > 其他好文 > 详细

Dubbo-RPC调用流程(图)

时间:2020-06-16 12:53:15      阅读:73      评论:0      收藏:0      [点我收藏+]

标签:ice   moni   try   根据   本地   服务   channel   Stub   ret   

 
RPC 起源
RPC 这个概念术语在上世纪 80 年代由 Bruce Jay Nelson 提出。这里我们追溯下当初开发 RPC 的原动机是什么?在 Nelson 的论文 "Implementing Remote Procedure Calls" 中他提到了几点:
  • 简单:RPC 概念的语义十分清晰和简单,这样建立分布式计算就更容易。
  • 高效:过程调用看起来十分简单而且高效。
  • 通用:在单机计算中过程往往是不同算法部分间最重要的通信机制。
通俗一点说,就是一般程序员对于本地的过程调用很熟悉,那么我们把 RPC 作成和本地调用完全类似,那么就更容易被接受,使用起来毫无障碍。Nelson 的论文发表于 30 年前,其观点今天看来确实高瞻远瞩,今天我们使用的 RPC 框架基本就是按这个目标来实现的。
Nelson 的论文中指出实现 RPC 的程序包括 5 个部分:
  • User
  • User-stub
  • RPCRuntime
  • Server-stub
  • Server
技术图片
pack:包装
 
 
RPC 工作原理
RPC的设计由Client,Client stub,Network ,Server stub,Server构成。 其中Client就是用来调用服务的,Cient stub是用来把调用的方法和参数序列化的(因为要在网络中传输,必须要把对象转变成字节),Network用来传输这些信息到Server stub, Server stub用来把这些信息反序列化的,Server就是服务的提供者,最终调用的就是Server提供的方法。
技术图片
  1. Client像调用本地服务似的调用远程服务;
  2. Client stub接收到调用后,将方法、参数序列化
  3. 客户端通过sockets将消息发送到服务端
  4. Server stub 收到消息后进行解码(将消息对象反序列化)
  5. Server stub 根据解码结果调用本地的服务
  6. 本地服务执行(对于服务端来说是本地执行)并将结果返回给Server stub
  7. Server stub将返回结果打包成消息(将结果消息对象序列化)
  8. 服务端通过sockets将消息发送到客户端
  9. Client stub接收到结果消息,并进行解码(将结果消息反序列化)
  10. 客户端得到最终结果。
 
 
 
Dubbo中的RPC调用流程图
技术图片
 
Dubbo官网
技术图片
 
 
 
一、客户端执行流程
执行main(String[]) 
首先服务消费者通过代理对象 Proxy 发起远程调用,即demoService是一个代理bean,执行proxy0.sayHello(String) ,在sayHello方法中当执行到handler.invoke(this, methods[0], args)时
1.调用InvocationHandler
         执行InvokerInvocationHandler.invoke(Object, Method, Object[])
2.调用invoker
         执行MockClusterInvoker<T>.invoke(Invocation)
         执行服务降级FailoverClusterInvoker<T>(AbstractClusterInvoker<T>).invoke(Invocation)
执行RegistryDirectory$InvokerDelegate<T>(InvokerWrapper<T>).invoke(Invocation) 
3.过滤器链处理
ConsumerContextFilter.invoke(Invoker<?>, Invocation) 
FutureFilter.invoke(Invoker<?>, Invocation) 
MonitorFilter.invoke(Invoker<?>, Invocation)
4.调用invoker
ListenerInvokerWrapper<T>.invoke(Invocation)
DubboInvoker<T>(AbstractInvoker<T>).invoke(Invocation)
5.调用ExchangeClient
ReferenceCountExchangeClient.request(Object, int) 
HeaderExchangeClient.request(Object, int) 
6.执行ExchangeChannel
         HeaderExchangeChannel.request(Object, int),执行channel.send方法向服务端发起请求


二、服务提供者执行流程
1.当服务端接收到来自客户端的请求后,开始执行ChannelEventRunnable中的run() 方法
2.执行ChannelHandler
DecodeHandler.received(Channel, Object) 
HeaderExchangeHandler.received(Channel, Object)
HeaderExchangeHandler.handleRequest(ExchangeChannel, Request) 
3.执行Protocol
        DubboProtocol$1.reply(ExchangeChannel, Object) 
4.过滤器链处理
EchoFilter.invoke(Invoker<?>, Invocation)
ClassLoaderFilter.invoke(Invoker<?>, Invocation) 
GenericFilter.invoke(Invoker<?>, Invocation) 
ContextFilter.invoke(Invoker<?>, Invocation)
TraceFilter.invoke(Invoker<?>, Invocation) 
TimeoutFilter.invoke(Invoker<?>, Invocation) 
MonitorFilter.invoke(Invoker<?>, Invocation)
ExceptionFilter.invoke(Invoker<?>, Invocation) 
5.执行Invoker调用
RegistryProtocol$InvokerDelegete<T>(InvokerWrapper<T>).invoke(Invocation)
DelegateProviderMetaDataInvoker<T>.invoke(Invocation) 
6.代理类调用
JavassistProxyFactory$1(AbstractProxyInvoker<T>).invoke(Invocation) 
7.Wrapper调用方法
        Wrapper1.invokeMethod(Object, String, Class[], Object[]) 
8.执行Impl的调用
        DemoServiceImpl.sayHello(String)
 
说明:
服务消费者执行如下代码时
DemoService demoService = (DemoService) context.getBean("demoService"); 
String hello = demoService.sayHello("world"); 

 

获得demoService代理类,执行hello方法直接调用其代理类的sayHello方法
public java.lang.String sayHello(java.lang.String arg0){
    Object[] args = new Object[1]; 
    args[0] = ($w)$1; 
    Object ret = handler.invoke(this, methods[0], args); 
    return (java.lang.String)ret;
}

 

handler是一个InvokerInvocationHandler类型,InvocationHandler是其接口
技术图片
 

Dubbo-RPC调用流程(图)

标签:ice   moni   try   根据   本地   服务   channel   Stub   ret   

原文地址:https://www.cnblogs.com/caoxb/p/13140287.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!