最近我拜读了mindwind的一片博客文章深入浅出 RPC - 深入篇,希望通过Dubbo深入学习RPC架构设计,在此结合RPC架构的原理,解析Dubbo是如何实现RPC架构的。

RPC架构模型

RPC架构的主要目的是在构建分布式系统时,调用远程方法就如同调用本地方法一样方便快捷,简化开发,提高效率。

我们看看下面这张图,了解一下RPC架构的主要组成部分及调用关系:

以上图片引自mindfloating的博客

上图左侧是调用者,右侧是方法提供端。我们分别解释一下上图的各模块的职责:

从左侧开始,Caller是调用者;RpcClient是Rpc协议定义的客户端,包括远程接口的地址列表及调用方式的信息等,Caller导入RpcClient;RemoteAPI表示远程接口;RpcProxy是一个对远程方法调用的代理组件,封装了远程过程调用的细节,可以包括加载地址列表,寻址,调用集群模块实现负载均衡、高可用,查找调用信息,调用RpcInvoker等;RpcInvoker是具体的RemoteAPI的调用者封装对象,它包含了一个具体接口方法的地址、调用方式等信息,并提供了调用处理方法;RpcConnector负责封装实现网络通信细节,如建立会话通道,发送数据请求和接收返回值数据;RpcProtocol是Rpc协议规范,定义了数据序列化和反序列化方法,如何解析地址信息等细节。

右侧为接口服务端,RpcAcceptor类似RpcConnector,封装实现网络通信细节,接收请求数据,发送本地接口处理后的返回值给客户端;RpcProcessor负责线程池管理,发起本地方法调用等;服务端RpcInvoker是本地API的调用者,通过反射技术调用指定接口的方法;Callee是服务端的本地接口类,导出RPC服务为RpcServer,客户端Caller将其作为RpcClient导入.

我们按照以上RPC的调用流程和各组件职责,聊一聊Dubbo是如何实现的。

Dubbo的RPC架构实现

Dubbo的调用关系如下图所示,以注册中心Registry为中心,Provider即服务提供者,将服务export出来注册(1、register)存储到Registry,Consumer即客户端调用者,从Registry订阅所关心的服务(2、subscribe),首次订阅时拉取订阅服务所有的地址列表(服务提供者注册到Registry上的信息),当订阅服务有更新(地址变更或有新的地址注册加入),Consumer收到注册中心的服务更新通知(3、notify),以上是服务端export的过程。

客户端发起RPC调用时,首先从服务地址列表里refer()指定的服务,这其中有服务寻址和从集群中筛选最终指向一个服务的过程,这就是import的过程。得到某个服务指向,则发起远程调用(4、invoke)。

以上图片引自Dubbo官方用户手册

那么Dubbo具体是如何实现RPC的整个过程的呢?对应RPC模型,Dubbo相应的组件又是如何实现和交互的?下图展示了Dubbo整个设计思路。

以上图片引自Dubbo官方用户手册

图例说明:

  • 图中左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口,位于中轴线上的为双方都用到的接口。
  • 图中从下至上分为十层,各层均为单向依赖,右边的黑色箭头代表层之间的依赖关系,每一层都可以剥离上层被复用,其中,Service 和 Config 层为 API,其它各层均为 SPI。
  • 图中绿色小块的为扩展接口,蓝色小块为实现类,图中只显示用于关联各层的实现类。
  • 图中蓝色虚线为初始化过程,即启动时组装链,红色实线为方法调用过程,即运行时调时链,紫色三角箭头为继承,可以把子类看作父类的同一个节点,线上的文字为调用的方法。

接下来我们对应RPC架构模型的组件谈谈Dubbo的设计。

export和import

Dubbo服务端接口export(导出)是将接口信息注册到注册中心Registry的过程。而客户端import(导入)远程接口是通过从注册中心Registry订阅远程服务接口,收到通知后拉取到本地的过程。
注册和订阅的过程,不需要修改服务端本地的类和方法,只需保证客户端和服务端共同引用一个包含接口的jar包。服务端和客户端分别编写简单的dubbo接口配置xml文件(或注解的方式),容器启动时就自动注册和订阅了。

客户端调用的过程

看上图Config层的橙色小圆点,红色实线剪头为调用链。客户端invoke远程API(Interface),实际是调用了Proxy层的RpcProxy,proxy又调用集群组件Cluster,从集群中筛选出一个Invoker作为调用者发起调用。

我们看到,在Cluster层中筛选的过程调用了Directory(实现类为RegistryDirectory)、Router、LoadBalance,分别通过Directory实现了服务的高可用,通过Router实现了智能路由功能,通过LoadBalance实现了负载均衡。

从集群模块中筛选出一个Invoker后执行invoke()方法执行方法调用,到了Protocol协议层,经过Filter组件做拦截过滤处理,如用户名、密码验证等可在此处理。过滤通过后,调用Protocol实现类如DubboProtocol或HessianProtocol等的invoke()方法。

具体的协议实现类(如DubboProtocol)会请求ExchangeClient组件,它封装了具体的数据通讯细节,是底层数据通信的代理层。因此它自然会调用底层的通信组件(默认是Netty)实现Client建立连接、Server绑定端口和数据传输(request、return)的功能。

数据传输前需要数据序列化,服务端接收到数据需要反序列化,这些都靠序列化组件实现。Codec是序列化组件的代理层,具体序列化协议,默认是Hessian,还可选择Kryo,Thrift(被Dubbo改造,与原Thrift不兼容),dubbo, hessian2, java, json等,具体参见Dubbo用户手册

服务端调用

服务端接收到客户端的请求后,反序列化数据,通过DubboHandler协议处理请求,找到注册的本地Exporter,触发invoke(),经过过滤器处理后,调用Invoker代理层,触发真正的本地接口调用,返回数据序列化后发送给客户端。

以上内容以RPC模型为基础,分析总结了Dubbo实现RPC的大体流程,后续我还会分别针对某些组件展开讨论Dubbo的设计实现。

Dubbo架构深入篇----RPC实现总结的更多相关文章

  1. 远程服务调用RPC框架介绍,微服务架构介绍和RPC框架对比,dubbo、SpringClound对比

    远程服务调用RPC框架介绍,微服务架构介绍和RPC框架对比,dubbo.SpringClound对比 远程服务调用RPC框架介绍,RPC简单的来说就是像调用本地服务一样调用远程服务. 分布式RPC需要 ...

  2. Dubbo架构设计详解-转

    Dubbo架构设计详解  2013-09-03 21:26:59    Yanjun Dubbo是Alibaba开源的分布式服务框架,它最大的特点是按照分层的方式来架构,使用这种方式可以使各个层之间解 ...

  3. 微服务架构介绍和RPC框架对比

    微服务架构介绍和RPC框架对比 1.微服务架构 1.1 特征 自动化部署,端点智能化,语言和数据的去中心化控制. 1.2架构 一种将一个单一应用程序开发为一组小型服务的方法,每个服务运行在自己的进程中 ...

  4. dubbo系列一:dubbo介绍、dubbo架构、dubbo的官网入门使用demo

    一.dubbo介绍 Dubbo是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的RPC实现服务的输出和输入功能,可以和Spring框架无缝集成.简单地说,dubbo是一个基于Spri ...

  5. 深入浅出微服务框架dubbo(一):基础篇

    一.基础篇 1.1 开篇说明 dubbo是一个分布式服务框架,致力于提供高性能透明化RPC远程调用方案,提供SOA服务治理解决方案.本文旨在将对dubbo的使用和学习总结起来,深入源码探究原理,以备今 ...

  6. Dubbo API 笔记——Dubbo架构与使用

    转载于: https://blog.csdn.net/benhuo931115/article/details/78457149 架构演变 单一应用架构 所有功能部署在一个应用上,用于简化增删改查工作 ...

  7. Dubbo+Zookeeper(二)Dubbo架构

    上次更新博客已经是一年前,这一年发生了很多事,并不顺利,甚至有些痛苦,不过不管怎样,不要停止学习,只有学习才能让你变强,应对更多不安定. 一.RPC概念 Dubbo服务是一个RPC框架,那我们首先就要 ...

  8. 基于dubbo框架下的RPC通讯协议性能测试

    一.前言 Dubbo RPC服务框架支持丰富的传输协议.序列化方式等通讯相关的配置和扩展.dubbo执行一次RPC请求的过程大致如下:消费者(Consumer)向注册中心(Registry)执行RPC ...

  9. VS2010+MVC4+Spring.NET2+NHibernate4-传统三层架构-前篇

    VS2010+MVC4+Spring.NET2+NHibernate4 - 传统三层架构 - 前篇 一直追求使用开源项目,就因一个字:懒! 一直想整理一下的,却一直懒到现在!从当初用的MVC3到现在的 ...

随机推荐

  1. 一次傻乎乎的错误QAQ

    东北联赛上有一道题,数据范围是2^60,当时不记得long long的范围,于是写了一个程序试了一下,把队友带入了一个大数的大坑QAQ(蠢哭). 当时写的代码是这样的: #include<ios ...

  2. 进阶1:Linux 环境准备_ 设置网络IP_安装火狐浏览器

    VM 已安装 centos6.5 Final 已安装 配置好了Linux  IP ,并能ping  通 ,例如 : ping www.baidu.com 设置LINUX 网络IP: https://j ...

  3. 小程序swiper实现订单页面

    小程序swiper实现订单页面 myOrder.wxml <!--pages/myorder/myorder.wxml--> <view class="swiper-tab ...

  4. lunwenzhunbei

    1,android sensors introduction http://developer.android.com/guide/topics/sensors/sensors_overview.ht ...

  5. SqlServer2012 File Table文件表

    SQL Server 2012 提供一种特殊的“文件表”,也称为“FileTable”. FileTable 是一种专用的用户表,它包含存储 FILESTREAM 数据的预定义架构以及文件和目录层次结 ...

  6. jni中arm64-v8a,armeabi-v7a,armeabi文件夹的意义和用法<转>

    jni中arm64-v8a,armeabi-v7a,armeabi文件夹的意义和用法 起因 之前并没有关注这块,直到:您的应用被拒绝,原因:xplay5sQ心里点击笑值点击拍照显示停止运行,查看发过来 ...

  7. ES5 Object.defineProperties / Object.defineProperty 的使用

    临时笔记,稍后整理 var obj = { v: , render: function () { console.log(") } }; // Object.defineProperties ...

  8. Map 接口有哪些类

    Map接口 Map提供了一种映射关系,其中的元素是以键值对(key-value)的形式存储的,能够实现根据key快速查找value:Map中的键值对以Entry类型的对象实例形式存在:建(key值)不 ...

  9. 1.k8s.资源清单

    #k8s常用资源 工作负载:Pod,rs(ReplicasSet),deploy(Deployment),sts(StatefulSet),ds(DaemonSet),Job,Cronjob 服务发现 ...

  10. 当我写下Map<String,Object> map = new HashMap<>() https://www.jianshu.com/p/6b2e350e99be

    当我写下Map<String,Object> map = new HashMap<>();我到底在写什么? 我什么时候会写HashMap? 一个函数同时需要返回 多种 状态的情 ...