Dubbo-RPC调用流程(图)

Posted cao_xiaobo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Dubbo-RPC调用流程(图)相关的知识,希望对你有一定的参考价值。

 
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调用流程(图)的主要内容,如果未能解决你的问题,请参考以下文章

在片段的后按防止使用导航图调用前一个片段的 onViewCreated

Android 逆向ART 脱壳 ( DexClassLoader 脱壳 | DexClassLoader 构造函数 | 参考 Dalvik 的 DexClassLoader 类加载流程 )(代码片段

Android 逆向ART 脱壳 ( DexClassLoader 脱壳 | DexClassLoader 构造函数 | 参考 Dalvik 的 DexClassLoader 类加载流程 )(代码片段

VSCode自定义代码片段——git命令操作一个完整流程

VSCode自定义代码片段15——git命令操作一个完整流程

VSCode自定义代码片段15——git命令操作一个完整流程