Dubbo

Dubbo(读音[ˈdʌbəʊ])是阿里巴巴公司开源的一个高性能优秀的服务框架,使得应用可通过高性能的 RPC 实现服务的输出和输入功能,可以和 [1] Spring框架无缝集成。

Dubbo是一款高性能、轻量级的开源Java RPC框架

什么是RPC?

RPC(Remote Procedure Call) 即远程过程调用,通过名字我们就能看出 RPC 关注的是远程调用而非本地调用。

为什么要RPC?,假如我们有两台服务器,现在服务器A想要调用服务器B的一个本地方法要怎么做?

服务器A和服务器B各自开一个服务A通过网络编程传输要调用的方法和参数给服务器B服务器B将本地方法调用后的结果通过网络返回给AA解析B返回的结果

从上面的步骤可以看出来工作量是非常大的,不仅要考虑底层传输方式使用TCP还是UDP,并且还需要对传输的数据进行序列化和反序列化等等

而RPC框架可以让你不需要关心这些底层,你只需要像调用本地方法一样调用远程方法,是不是很方便?

RPC的原理

客户端Stub(桩):可以理解为一个代理类。主要的工作就是把你调用的方法、类、方法参数等信息传递到服务端服务端Stub(桩):在接收到客户端执行方法的请求后,去执行对应的方法然后返回给客户端的Stub进行解析,再返回给客户端方法

举个栗子

客户端A的hello方法调用了服务器B的hi方法

步骤:

A以本地调用的方式调用远程服务客户端Stub接收到请求方法、请求参数后,将这些信息封装成为一个请求类假设为RpcRequest,并将这个类序列化客户端Stub根据请求的方法去注册中心(注册中心仔细说)寻找提供该方法的服务器IP、端口,并将序列化后的请求类发送到目标服务器服务端Stub收到消息后将消息反序列化为Java对象:RpcRequest服务端Stub根据RpcRequest中的类、方法、方法参数等信息调用本地的方法;服务端Stub得到方法执行结果后将结果封装为RpcResponse类,序列化后传输给客户端客户端Stub接收到消息并将消息反序列化为Java对象RpcResponse,客户端只需要从RpcResponse中取出数据即可,完成远程调用

进入正题

为什么要使用Dubbo?

上面介绍了RPC框架可以让你不需要关心调用底层,你只需要像调用本地方法一样调用远程方法

并且Dubbo还有六大核心能力

面向接口代理的高性能RPC调用智能负载均衡服务自动注册和发现高度可拓展能力运行期流量调度可视化的服务治理与运维

总的来说,Dubbo不仅能帮助我们实现RPC,还提供了一些其他开箱即用的功能比如负载均衡

这些功能有什么用呢?

随着互联网的发展,网站的规模越来越大,用户数量越来越多。单一应用架构、垂直应用架构无法满足我们的需求,这个时候分布式服务架构就诞生了。

分布式服务架构下,系统被拆分成不同的服务比如短信服务、安全服务,每个服务独立提供系统的某个核心服务。

我们可以使用 Java RMI(Java Remote Method Invocation)、Hessian 这种支持远程调用的框架来简单地暴露和引用远程服务。但是!当服务越来越多之后,服务调用关系越来越复杂。当应用访问压力越来越大后,负载均衡以及服务监控的需求也迫在眉睫。

而这时候Dubbo的作用就体现出来了

负载均衡:同一个服务部署在不同的机器时该调用哪一台机器的服务。服务调用链路生成:随着系统的发展,服务越来越多,服务件依赖关系变得错综复杂,甚至分不清哪一个应用要在哪一个应用之前启动。Dubbo可以为我们解决服务之间互相时如何调用的服务访问压力以及时长统计、资源调度和治理:基于访问压力实时管理集群容量,提高集群利用率

Dubbo架构

Provider(服务提供方),提供远程调用方法的调用服务Consumer(服务消费方),调用远程方法Registry(注册中心),提供服务注册与服务发现的功能,常见的注册中心有Eureka、Nacos、ZookeeperMoniter(监控中心),统计服务的调用次数和调用时间的监控中心Containner(容器):服务运行容器

调用关系说明:

服务容器负责启动,加载,运行服务提供者。服务提供者在启动时,向注册中心注册自己提供的服务。服务消费者在启动时,向注册中心订阅自己所需的服务。注册中心返回服务提供者地址列表给消费者,如果有变更,注册中心将基于长连接推送变更数据给消费者。服务消费者,从提供者地址列表中,基于软负载均衡算法,选一台提供者进行调用,如果调用失败,再选另一台调用。服务消费者和提供者,在内存中累计调用次数和调用时间,定时每分钟发送一次统计数据到监控中心。

重要知识点详解

注册中心负责服务地址的注册与查找,相当于目录服务,服务提供者和消费者只在启动时与注册中心交互,注册中心不转发请求,压力较小 看一下注册中心到底存了什么东西(以nacos为例),能够让客户端远程调用服务,打开nocos的web管理页面 点进详情

配置内容

内容太多,只提炼关键点

服务接口:com.hwq.goatapicommon.service.InnerInterfaceInfoService接口方法:getInterfaceInfo服务提供者的IP地址:bind.ip=192.168.9.172服务提供者的端口号:bind.port=20880方法参数类型:java.lang.String, java.lang.String方法返回类型:com.hwq.goatapicommon.model.entity.InterfaceInfo服务版本号:release=3.0.9Dubbo 版本:dubbo=2.0.2服务发布时间戳:timestamp=1709454944034服务是否为动态注册:dynamic=true服务是否为泛化调用:generic=false服务是否为后台服务:background=false

根据上面的内容,服务调用者可以构造调用请求,但是这些东西dubbo都在底层帮你封装好了,你只需要调用即可

为什么我的后端部署在8080端口,但是nacos里面显示的远程方法提供者端口为20880?

在Dubbo中,8080端口一般是应用程序的HTTP服务端口,而20880端口则是Dubbo服务的默认端口。这两者是不同的概念。

8080端口:通常是用来提供HTTP服务的端口,比如你的后端服务可能会使用8080端口来接收HTTP请求,提供Web服务或者API接口。20880端口:是Dubbo服务提供者默认的端口,用于Dubbo协议通信。Dubbo框架内部会在这个端口上监听服务消费者的请求,并提供服务调用的功能。

所以,虽然你的后端服务部署在8080端口,但Dubbo服务的提供者端口显示为20880是正常的。这是因为Dubbo服务通常使用自己的协议进行通信,而不是HTTP协议,因此它需要一个独立的端口来监听Dubbo请求

接着说其他的重点

注册中心,服务提供者,服务消费者三者之间均为长连接,监控中心除外 注册中心通过长连接感知服务提供者的存在,服务提供者宕机,注册中心将立即推送事件通知消费者 注册中心和监控中心全部宕机,不影响已运行的提供者和消费者,消费者在本地缓存了提供者列表 注册中心和监控中心都是可选的,服务消费者可以直连服务提供者 服务提供者无状态,任意一台宕掉后,不影响使用 服务提供者全部宕掉后,服务消费者应用将无法使用,并无限次重连等待服务提供者恢复

Dubbo 工作原理

图中从下至上分为十层,各层均为单向依赖,右边的黑色箭头代表层之间的依赖关系,每一层都可以剥离上层被复用,其中,Service 和 Config 层为 API,其它各层均为 SPI。关于SPI是什么可以看我之前的文章:SPI详解

各层说明:

第一层:service层,接口层,给服务提供者和消费者来实现的第二层:config层,配置层,主要是对dubbo进行各种配置的第三层:proxy层,服务接口透明代理,生成服务的客户端 Stub 和服务器端 Skeleton第四层:registry层,服务注册层,负责服务的注册与发现第五层:cluster层,集群层,封装多个服务提供者的路由以及负载均衡,将多个实例组合成一个服务第六层:monitor层,监控层,对rpc接口的调用次数和调用时间进行监控第七层:protocol层,远程调用层,封装rpc调用第八层:exchange层,信息交换层,封装请求响应模式,同步转异步第九层:transport层,网络传输层,抽象mina和netty为统一接口第十层:serialize层,数据序列化层。网络传输需要。

Dubbo负载均衡策略

在集群负载均衡时,Dubbo 提供了多种均衡策略,默认为 random 随机调用。可以自行扩展负载均衡策略。

Random LoadBalance(默认,基于权重的随机负载均衡机制)

随机,按权重设置随机概率。在一个截面上碰撞的概率高,但调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。

RoundRobin LoadBalance(不推荐,基于权重的轮询负载均衡机制)

轮循,按公约后的权重设置轮循比率。存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。

LeastActive LoadBalance

最少活跃调用数,相同活跃数的随机,活跃数指调用前后计数差。使慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大。

ConsistentHash LoadBalance

一致性 Hash,相同参数的请求总是发到同一提供者。(如果你需要的不是随机负载均衡,是要一类请求都到一个节点,那就走这个一致性hash策略。)当某一台提供者挂掉时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。算法参见:http://en.wikipedia.org/wiki/Consistent_hashing缺省只对第一个参数 Hash,如果要修改,请配置 缺省用 160 份虚拟节点,如果要修改,请配置

配置方式

注解方式:

@Reference(url = "127.0.0.1:20880")

HelloService helloService;

Dubbo的序列化协议

不同的序列化协议对于数据传输的速率有着很大的影响,Dubbo支持使用者自定义底层的序列化协议

Dubbo支持的序列化协议

JDK自带序列化协议hessian2JSONkryoFST等等

一般情况下,不会选择JDK自带的序列化作为Dubbo的底层序列化协议

原因在于:

不支持跨语言调用:如果调用的是其他语言开发的服务时就不支持了性能差:相比于其他序列化框架性能更低,原因就是JDK序列化之后的字节数组体积较大,导致传输成本加大

序列化性能对比

下面的性能测试是由Dubbo官方给出的

总结

Dubbo 是 Alibaba 开源的分布式服务框架,并被广泛应用于各互联网公司。Dubbo只需要通过 Spring 配置的方式即可完成服务化,对于应用无入侵,其框架本身的成熟度以及文档的完善程度,基本都能满足各互联网公司的业务需求。

如果觉得本篇文章对于你理解有帮助,可否点个小赞;篇幅较长建议收藏﫠;关注一手等待后续更新更多干货

参考链接:Javaguide之Dubbo常见问题总结

精彩内容

评论可见,请评论后查看内容,谢谢!!!
 您阅读本篇文章共花了: