Dubbo原理以及服务的暴露、引用、调用、BIO、NIO

1 篇文章 0 订阅
1 篇文章 0 订阅

一、RPC原理

  • 一次完整的RPC调用流程(同步调用,异步另说)如下:

    1)服务消费方(client)调用以本地调用方式调用服务;

    2)client stub【客户端代理】接收到调用后负责将方法、参数等组装成能够进行网络传输的消息体;

    3)client stub找到服务地址,并将消息发送到服务端;

    4)server stub【服务端代理】收到消息后进行解码

    5)server stub根据解码结果调用本地的服务;

    6)本地服务执行并将结果返回给server stub;

    7)server stub将返回结果打包成消息并发送至消费方;

    8)client stub接收到消息,并进行解码

    9)服务消费方得到最终结果。

    RPC框架的目标就是要2~8这些步骤都封装起来,这些细节对用户来说是透明的,不可见的。

 二、Netty通信原理

  • Netty是一个异步事件驱动的网络应用程序框架, 用于快速开发可维护的高性能协议服务器和客户端。它极大地简化并简化了TCP和UDP套接字服务器等网络编程。

  • BIO:同步阻塞式IO,服务器实现模式为一个连接一个线程,即客户端有连接请求时服务器端就需要启动一个线程进行处理,如果这个连接不做任何事情会造成不必要的线程开销,当然可以通过线程池机制改善。 

  • NIO:同步非阻塞式IO,服务器实现模式为一个请求一个线程,即客户端发送的连接请求都会注册到多路复用器上,多路复用器轮询到连接有I/O请求【某个通道的状态都准备好】时才启动一个线程进行处理。 

  • Selector 一般称 为选择器 ,也可以翻译为 多路复用器

  • Connect(连接就绪)、Accept(接受就绪)、Read(读就绪)、Write(写就绪)

  • Netty的基本原理:

  • 原理图解析:

    1)启动Netty,并绑定一个 端口,比如:dubbo的20880【这样所有给这个端口发的数据Netty都能收到】

    2)初始化通道(Channel)

    3)注册到选择器(Selector)中,负责监听一个事件

    4)监听accept事件,通道已经准备就绪了,使用轮询的方式处理通道内的一些信息,这里也有一个任务队列,监听好了去做什么,监听就绪了去做什么,整个队列完成Netty就结束了

    5)处理方式:Netty与客户端建立连接,生成NioSocketChannel,这就是与客户端连接的通道

    6)把NioSocketChannel通道注册到Selector中,用它来监听Read、Write事件,相当于通道内数据读【发过去的数据都读好了】、写【可以给客户端通道里边写响应了】都准备就绪

    7)读写都准备就绪以后,就来处理这个事件,比如读准备就绪我们处理一个任务,写准备就绪我们处理一个任务,这些任务都会抛给任务队列,Netty就把这些队列执行完

     

    注意:两个监听的上边有一个boss和worker

    boss:是主线程,用来监听来自20880的所有连接准备就绪事件

    worker:当我们准备就绪以后需要做什么工作,把这个工作抛给worker,让worker来做

 三、Dubbo原理

  • dubbo原理 -框架设计 

  • 图例说明:

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

    各层说明:

    • config 配置层:【主要是来封装我们配置文件里边解析出来的一些信息】对外配置接口,以 ServiceConfigReferenceConfig 为中心,可以直接初始化配置类,也可以通过 spring 解析配置生成配置类
    • proxy 服务代理层:【帮我们利用代理的方式生成我们客户端的代理对象以及服务端的代理对象,代理对象那个来互相调用方法】服务接口透明代理,生成服务的客户端 Stub 和服务器端 Skeleton, 以 ServiceProxy为中心,扩展接口为 ProxyFactory
    • registry 注册中心层:【服务的发现与注册:服务注册到注册中心,消费者订阅服务】封装服务地址的注册与发现,以服务 URL 为中心,扩展接口为 RegistryFactoryRegistryRegistryService
    • cluster 路由层:【这层帮我们进行负载均衡,调用者调用服务,而服务可能在很多台机器上,这层帮助我们进行负载均衡】封装多个提供者的路由及负载均衡,并桥接注册中心,以 Invoker 为中心,扩展接口为 ClusterDirectoryRouterLoadBalance
    • monitor 监控层:【我们每一次的调用信息都会发送给监控层,可以在界面上展示监控数据】RPC 调用次数和调用时间监控,以 Statistics 为中心,扩展接口为 MonitorFactoryMonitorMonitorService
    • protocol 远程调用层:【封装整个RPC调用的,RPC的核心是ProtocolInvokerExporter,完成一次远程调用】封装 RPC 调用,以 InvocationResult 为中心,扩展接口为 ProtocolInvokerExporter
    • exchange 信息交换层:【创建一个客户端,一个服务端,两个架起管道,进行数据的互联互通】封装请求响应模式,同步转异步,以 RequestResponse 为中心,扩展接口为 ExchangerExchangeChannelExchangeClientExchangeServer
    • transport 网络传输层:【真正传输数据是用Transporter,而Transporter的底层是Netty框架】抽象 mina 和 netty 为统一接口,以 Message 为中心,扩展接口为 ChannelTransporterClientServerCodec
    • serialize 数据序列化层:【在整个传输的过程中数据要序列化才能网络传输,收到数据还要反序列化,拿到对象】可复用的一些工具,扩展接口为 SerializationObjectInputObjectOutputThreadPool

    关系说明

    • 在 RPC 中,Protocol 是核心层,也就是只要有 Protocol + Invoker + Exporter 就可以完成非透明的 RPC 调用,然后在 Invoker 的主过程上 Filter 拦截点。
    • 图中的 Consumer 和 Provider 是抽象概念,只是想让看图者更直观的了解哪些类分属于客户端与服务器端,不用 Client 和 Server 的原因是 Dubbo 在很多场景下都使用 Provider, Consumer, Registry, Monitor 划分逻辑拓普节点,保持统一概念。
    • 而 Cluster 是外围概念,所以 Cluster 的目的是将多个 Invoker 伪装成一个 Invoker,这样其它人只要关注 Protocol 层 Invoker 即可,加上 Cluster 或者去掉 Cluster 对其它层都不会造成影响,因为只有一个提供者时,是不需要 Cluster 的。
    • Proxy 层封装了所有接口的透明化代理,而在其它层都以 Invoker 为中心,只有到了暴露给用户使用时,才用 Proxy 将 Invoker 转成接口,或将接口实现转成 Invoker,也就是去掉 Proxy 层 RPC 是可以 Run 的,只是不那么透明,不那么看起来像调本地服务一样调远程服务。
    • 而 Remoting 实现是 Dubbo 协议的实现,如果你选择 RMI 协议,整个 Remoting 都不会用上,Remoting 内部再划为 Transport 传输层和 Exchange 信息交换层,Transport 层只负责单向消息传输,是对 Mina, Netty, Grizzly 的抽象,它也可以扩展 UDP 传输,而 Exchange 层是在传输层之上封装了 Request-Response 语义。
    • Registry 和 Monitor 实际上不算一层,而是一个独立的节点,只是为了全局概览,用层的方式画在一起。

     

四、启动解析、加载配置文件

  •  Spring解析配置文件中每一个标签都会有一个总接口 BeanDefinitionparser 定义的解析器,它的实现方法有一个DubboBeanDefinitionParser,里边有一个 parse 方法来解析标签,每个标签依次进入进行解析

五、服务暴露流程

  • 当我们暴露服务的时候,要获取到invoker,获取到执行器,也就是getInvoker()方法,我们使用Protocol来暴露执行器的export(invoker),而Protocol我们使用两个DubboProtocol RegistryProtocol,都对应两个暴露者,DubboProtocol 会帮我们开启服务器,RegistryProtocol 会帮我们将服务注册到注册中心【每一个服务以及它的URL地址信息都保存在注册表ProviderConsumerRegTable 中,注册表中相当于缓存了一个url地址对应哪个服务的执行器,执行器里边有真正的服务

六、服务引用流程

<dubbo:reference interface="cn.e3mall.service.ItemService" id="itemService" />
  • reference标签里边的interface会自动注入的ServiceImpl,自动注入Spring就会在容器中找ReferenceBean会调用FactooyBean中的方法getObject方法,它返回的对象就会作为标签配置返回的对象,并且 init() 初始化,主要来创建对象,所谓的创建对象就是 Protocol 来引用远程服务,怎么引用呢,我们有两个 Protocol 分别是 DubboProtocol RegistryProtocol DubboProtocol负责跟远程的20880服务器进行连接创建一个客户端,RegistryProtocol 从注册中心订阅服务,并且将我们创建的客户端信息 invoke 信息,保存到注册表 ProviderConsumerRegTable 中,返回封装好的 invoke ,创建 invoke 的代理对象 invoker,之后返回 invoker 代理

七、服务调用流程

  • Proxy 是代理对象,如果有要做其他功能使用Filter结构,没有的话使用Cluster【封装多个invoker】,如果有多个invoker的话我们可以选择一种LoadBalance负载均衡机制,调用错了还会有重试,在负载均衡调用期间还有其他的Filter来介入统计一些信息数据,由于我们使用dubbo协议来远程调用,所以最终我们真正执行功能的是DubboInvoker,而调用的底层是Client发送请求,Client底层使用Netty的客户端,连接我们目标端口的服务器,来发送请求,服务器收到请求数据之后,我们要进行解码,来整个返回,把我们整个返回数据交给代理对象,由代理对象交给我们

 

  • 1
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值