栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 前沿技术 > 大数据 > 大数据系统

dubbo原理与核心功能

dubbo原理与核心功能

Dubbo 是一款微服务开发框架,它提供了【RPC通信】与【服务治理】两大关键能力。

RPC远程调用技术

RPC 全称 Remote Procedure Call,是一种进程间通信方式。它允许程序调用另一个地址空间(通常是共享网络的另一台机器上)的过程或函数,而不用程序员显式编码这个远程调用的细节。

RPC是一种抽象的概念,像常见的 RMI、WebService、Http 等是它的具体实现。

dubbo 也对 RPC 做了具体实现,制定了 dubbo协议,默认使用的就是 dubbo协议。

dubbo服务发现基本工作原理

服务发现,即消费端自动发现服务地址列表的能力,是微服务框架需要具备的关键能力,借助于自动化的服务发现,微服务之间可以在无需感知对端部署位置与 IP 地址的情况下实现通信。

实现服务发现的方式有很多种,Dubbo 提供的是一种 Client-based 的服务发现机制,通常还需要部署额外的第三方注册中心组件来协调服务发现过程,如常用的 Nacos、Zookeeper 等。

工作原理图

其中:Registry表示注册中心、Provider表示服务提供者、Consumer表示服务消费者。

流程说明

    Provider绑定指定端口并启动服务Provider连接Registry,并将{本机IP、端口、应用信息和提供服务信息}发送至Registry存储Consumer连接Registry ,并发送{应用信息、所求服务信息}至RegistryRegistry根据Consumer所求服务信息匹配对应的Provider列表发送至Consumer应用进行缓存Consumer在发起远程调用时基于缓存的Provider列表择其一发起调用Provider状态变更会实时通知Registry,再由Registry实时推送至Consumer

优势

    Consumer与Provider解偶,双方都可以横向增减节点数注册中心本身可做集群,可动态增减节点,并且任意一台宕掉后,将自动切换到另一台去中心化,双方不直接依懒注册中心,即使注册中心全部宕机短时间内也不会影响服务的调用(Consumer本地缓存Provider列表)服务提供者无状态,任意一台宕掉后,不影响使用

dubbo调用模块原理

dubbo调用模块涉及透明代理、负载均衡、容错机制、调用方式等。

调用流程:

透明代理

通过动态代理技术,屏蔽远程调用细节以提高编程友好性。

客户端在启动时,创建bean的过程中,会给接口创建代理对象。代码是在ReferenceConfig的createProxy方法中。

默认使用Javassist来实现动态代理。使用的类是JavassistProxyFactory。

编程的时候像本地调用接口一样,但实际调用时通过代理对象来操作,通过代理对象调用时可以远程调用。

容错机制

dubbo支持多种容错机制(默认Failover):

容错机制说明

失败自动切换(Failover)

失败自动切换,当出现失败,重试其它服务器。通常用于读操作,但重试会带来更长延迟。可通过 retries="2" 来设置重试次数(不含第一次)。

快速失败(Failfast)

快速失败,只发起一次调用,失败立即报错。通常用于非幂等性的写操作,比如新增记录。

失败安全(Failsafe)

失败安全,出现异常时,直接忽略。通常用于写入审计日志等操作。

失败自动恢复(Failback)失败自动恢复,后台记录失败请求,定时重发。通常用于消息通知操作。
并行调用(Forking)并行调用多个服务器,只要一个成功即返回。通常用于实时性要求较高的读操作,但需要浪费更多服务资源。可通过 forks="2" 来设置最大并行数。
广播调用(Broadcast)广播调用所有提供者,逐个调用,任意一台报错则报错。通常用于通知所有提供者更新缓存或日志等本地资源信息。
其他......

以 Failover 机制为例,源码是在 FailoverClusterInvoker 中,如果 retries="2",那么最多尝试调用3次。代码中就是循环3次,只要成功,立刻return。

负载均衡

Dubbo支持以下几种负载均衡策略,默认为【加权随机】:

策略说明
加权随机(Random)按权重设置随机概率。默认权重相同。
加权轮循 (RoundRobin)按公约后的权重设置轮询比率,循环调用节点。默认权重相同。
加权最少活跃调用优先(LeastActive)活跃数越低,越优先调用,相同活跃数的进行加权随机。
加权最短响应优先(ShortestResponse)在最近一个滑动窗口中,响应时间越短,越优先调用。相同响应时间的进行加权随机。
一致性哈希(ConsistentHash)相同参数的请求总是发到同一提供者。

客户端启动时,会调用Protocol的refer方法,来引用服务,最终实现是在DubboProtocol的protocolBindingRefer方法中,获取服务提供者列表,缓存起来(Set> invokers)。

当调用时,从缓存中根据负载均衡策略,取出一个服务提供者。

代码中,进行负载均衡是在 FailoverClusterInvoker(以Failover容错策略为例)的 doInvoke 中调用的,具体实现是在 AbstractClusterInvoker 的 doSelect() 方法中。

调用方式

默认调用方式为:异步调用,同步等待结果返回。也就是“异步转同步”。

从 version 2.7.0 开始,Dubbo 的所有异步编程接口开始以 CompletableFuture 为基础。

接口返回的是一个 AsyncRpcResult 对象,这个对象是立即返回的,但是里面并没有实际结果,接口调用未结束。

之后会调用 AsyncRpcResult 的 get 方法尝试获取实际结果,内部调用了 CompletableFuture 的 waitingGet 方法。在 waitingGet 方法中,通过 while 循环实现阻塞,直到获取实际结果(result)才返回,接口调用结束。以此达到异步转同步的效果。

协议

Dubbo 支持 dubbo、rmi、hessian、http、webservice、thrift 等多种协议。默认使用"dubbo协议"。

"dubbo协议"采用单一长连接和NIO异步通讯,适合于小数据量大并发的服务调用,以及服务消费者机器数大于服务提供者机器数的情况。他不适合传送大数据量的服务,比如传文件,传视频等。

当使用"dubbo协议"时,url以"dubbo://"开头,类似如下这样:

dubbo://127.0.0.1:20880/com.xujingyi.contract.service.UserService

dubbo协议报文编码:

magic2字节

类似java字节码文件里的魔数,用来判断是不是dubbo协议的数据包。

魔数是常量0xdabb,用于判断报文的开始。

flag1字节

标志位, 一共8个地址位。

低四位用来表示消息体数据用的序列化工具的类型(默认hessian);

高四位中,第一位为1表示是request请求,第二位为1表示双向传输(即有返回response),第三位为1表示是心跳ping事件。

status1字节

状态位, 设置请求响应状态,dubbo定义了一些响应的类型。

具体类型见 com.alibaba.dubbo.remoting.exchange.Response

invoke id8字节消息id, long 类型。每一个请求的唯一识别id(由于采用异步通讯的方式,用来把请求request和返回的response对应上)
body length4字节消息体 body 长度, int 类型,即记录Body Content有多少个字节。

dubbo协议编码过程:

远程调用时,假设发送的是一个java对象,但是计算机处理的时候不认java对象、字符串这种,只认字节,所以需要先对消息体进行编码。编码时需要根据协议报文进行。

解码时根据协议报文的格式,解析前16个字节,根据它来准确得获取消息体。比如通过 body length 来确定消息体的长度,防止 Netty 粘包拆包导致获取的消息体不是想要的消息体。

底层通信机制

dubbo 客户端与服务端的通信,底层通过 netty 来实现的。

服务端

dubbo服务端在启动的时候,会通过DubboProtocol中的export方法暴露服务,在其中会创建Netty服务端。具体代码是NettyServer类中的doOpen()方法:

可以看到,这是标准的 Netty 服务端的代码。

Pipeline 中添加了"dubbo协议"的编解码处理器;还有用于处理心跳检测的 IdleStateHandler,负责检测Netty服务端与客户端的连接。

客户端 

dubbo客户端在启动时,会创建Netty客户端,具体代码是NettyClient类中的doOpen()方法:

Pipeline 中添加了"dubbo协议"的编解码处理器,还有用于处理心跳检测的 IdleStateHandler。 

客户端调用接口的时候,最终会调用到dubbo包中NettyChannel的send()方法来进行远程调用。而NettyChannel中的channel对象,就是Netty客户端的NioSocketChannel,通过NioSocketChannel来跟netty服务端进行通信。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/751407.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号