分布式(十一)Dubbo(上)

javaguide.cn
https://dubbo.apache.org/zh/docs/ Dubbo3文档
https://dubbo.apache.org/zh/docsv2.7/ Dubbo2.x文档
主要参考:框架设计实现细节
在这里插入图片描述

分布式基础

简单来说,分布式就是我们把整个系统拆分成不同的服务,然后将这些服务放在不同的服务器上,减轻单体服务的压力提高并发量和性能。
优点:
拆分服务,将每个服务单独部署在一台或多台机器,提高系统性能和并发量,满足日益增长的用户数量和性能需求。
根据业务拆分代码,交由不同的团队开发,提高开发效率,便于维护和扩展。

什么是Dubbo

https://dubbo.apache.org/zh/ 官网
Apache Dubbo 是一款高性能、轻量级的开源分布式服务框架
在这里插入图片描述

Apache Dubbo |ˈdʌbəʊ| 提供了六大核心能力:面向接口代理的高性能RPC调用,智能容错和负载均衡服务自动注册和发现,高度可扩展能力,运行期流量调度,可视化的服务治理与运维。

为什么要用Dubbo?
在分布式服务架构下,系统被拆分成多个服务。Dubbo可以实现高性能RPC,调用远程服务。随着服务数量增大,服务调用关系越来越复杂,Dubbo提供服务注册与发现功能、服务调用链路生成、服务治理与运维等功能。随着请求数量增大,Dubbo提供负载均衡的功能,实现部署在不同机器上的服务的调用。
Dubbo不仅能够应用在分布式系统中,也能够应用在现在比较火的微服务系统中(Spring Cloud 在微服务中应用更加广泛)。

为什么Dubbo能够提供高性能RPC?
提升性能需要从最耗时的两个方面入手:序列化、网络通信
序列化:Dubbo使用高效的 Java 序列化(Kryo 和 FST),二进制流。
网络通信:Dubbo采用全新的 RPC 通信协议 – Triple,基于HTTP2。

Dubbo支持的RPC协议:(消费者调用提供者)
dubbo hessian rmi http webservice thrift memcached redis. 官方推荐使用dubbo协议,默认端口20880.

Dubbo与Spring无缝结合。

Dubbo架构

参考:https://dubbo.apache.org/zh/docs/v2.7/dev/design/

工作原理:

https://github.com/apache/dubbo
在这里插入图片描述

容器启动时,创建Provider的服务实例,并注册到Registry
然后,Consumer订阅Registry中注册的服务
Registry将注册的服务信息发送给Consumer,同时,如果某个服务宕机了,Registry也会通知Consumer
Consumer通过接口代理调用远程服务
Monitor监控RPC调用次数和调用时间。

整体设计:

从下至上分为十层,各层均为单向依赖。
在这里插入图片描述
图中左边淡蓝背景的为服务消费方使用的接口,右边淡绿色背景的为服务提供方使用的接口,位于中轴线上的为双方都用到的接口。
图中从下至上分为十层,各层均为单向依赖,右边的黑色箭头代表层之间的依赖关系,每一层都可以剥离上层被复用,其中,Service 和 Config 层为 API,其它各层均为 SPI。
图中绿色小块的为扩展接口,蓝色小块为实现类,图中只显示用于关联各层的实现类。
图中蓝色虚线为初始化过程,即启动时组装链,红色实线为方法调用过程,即运行时调时链,紫色三角箭头为继承,可以把子类看作父类的同一个节点,线上的文字为调用的方法。
在这里插入图片描述
在RPC中,Protocol远程调用层是核心层,以 Invoker 为中心,只要有 Protocol + Invoker + Exporter 就可以完成非透明的 RPC 调用。
Proxy 层封装了所有接口的透明化代理,是实现调用远程方法像本地方法一样简单的关键。而在其它层都以 Invoker 为中心,只有到了暴露给用户使用时,才用 Proxy 将 Invoker 转成接口,或将接口实现转成 Invoker。
Remoting是Dubbo协议的实现,如果选择RMI协议(JDK自带),整个Remoting都不会被启用。Remoting再划为 Transport 传输层和 Exchange 信息交换层。Transport 层只负责单向消息传输,是对 Mina, Netty, Grizzly 的抽象,它也可以扩展 UDP 传输,而 Exchange 层是在传输层之上封装了 Request-Response 语义。
Cluster 的目的是将多个 Invoker 伪装成一个 Invoker,这样其它人只要关注 Protocol 层 Invoker 即可。
Serialize 对需要在网络传输的数据进行序列化。

模块分包:

在这里插入图片描述
container模块 为服务容器,用于部署运行服务,没有在层中画出。
protocol 层和 proxy 层都放在 rpc 模块中,这两层是 rpc 的核心,在不需要集群也就是只有一个提供者时,可以只使用这两层完成 rpc 调用。
transport 层和 exchange 层都放在 remoting 模块中,为 rpc 调用的通讯基础。

依赖关系:

在这里插入图片描述
图中小方块 Protocol, Cluster, Proxy, Service, Container, Registry, Monitor 代表层或模块,蓝色的表示与业务有交互,绿色的表示只对 Dubbo 内部交互。
图中背景方块 Consumer, Provider, Registry, Monitor 代表部署逻辑拓扑节点。
图中蓝色虚线为初始化时调用,红色虚线为运行时异步调用,红色实线为运行时同步调用。
图中只包含 RPC 的层,不包含 Remoting 的层,Remoting 整体都隐含在 Protocol 中。

核心角色

Consumer(client) Provider(server)
Registry 服务注册与发现(查找)中心,注册中心会返回服务提供者地址列表给消费者。如果Provider宕机,会推送事件给Consumer。
Monitor 监控中心,监控RPC调用次数和调用时间。
Continer服务运行容器,负责加载、运行服务提供者。
注:
Consumer Provider 是必须的,Registry和Monitor是非必须的。
Registry挂掉不影响已经运行的消费者和提供者,Consumer已经将Provider列表缓存到本地内存,服务消费者可以直连提供者。

Invoker

参考:https://dubbo.apache.org/zh/docs/v2.7/dev/implementation/#%E6%BB%A1%E7%9C%BC%E9%83%BD%E6%98%AF-invoker
简单来说,Invoker 就是 Dubbo 对远程调用的抽象
最重要的两种 Invoker:服务提供 Invoker 和服务消费 Invoker
在这里插入图片描述
dubbo远程调用过程:
用户代码通过服务提供者的proxy(客户端需要的接口,用户代码可以通过接口实例调用方法)调用其对应的Invoker,该Invoker再给Provider发送请求,当Provider的网络通讯层收到一个请求后,找到对应的Exporter实例,并调用它对应的AbstractProxyInvoker实例,从而真正调用具体的服务实现类。
假如我们需要调用一个远程方法,我们需要动态代理Proxy来屏蔽远程调用的细节。我们屏蔽掉的这些细节就依赖对应的 Invoker 实现, Invoker 实现了真正的远程服务调用。

远程调用细节

参考:https://dubbo.apache.org/zh/docs/v2.7/dev/implementation/#%E8%BF%9C%E7%A8%8B%E8%B0%83%E7%94%A8%E7%BB%86%E8%8A%82

服务暴露:服务提供者暴露一个服务的详细过程:(Protocol的export方法)

两个过程:一是具体服务(注册的接口实现类)到Invoker,二是Invoker转化为Exporter。
首先 ServiceConfig 类拿到对外提供服务的接口实现类 ref(如:HelloWorldImpl),然后通过 ProxyFactory 类的 getInvoker 方法使用 ref 生成一个 AbstractProxyInvoker 实例,到这一步就完成具体服务到 Invoker (AbstractProxyInvoker 实例)的转化。
Dubbo 处理服务暴露的关键就在 Invoker 转换到 Exporter 的过程,以 Dubbo 和 RMI 这两种典型协议的实现来进行说明:
Dubbo 协议的 Invoker 转为 Exporter 发生在 DubboProtocol 类的 export 方法,它主要是打开 socket 侦听服务,并接收客户端发来的各种请求,通讯细节由 Dubbo 自己实现
RMI 协议的 Invoker 转为 Exporter 发生在 RmiProtocol类的 export 方法,它通过 Spring 或 Dubbo 或 JDK 来实现 RMI 服务,通讯细节由 JDK 底层来实现
在这里插入图片描述

服务引入:服务消费者消费一个服务的详细过程:(Protocol的refer方法)

首先 ReferenceConfig 类的 init 方法调用 Protocol 的 refer 方法生成 Invoker 实例,这是服务消费的关键。
接下来调用ProxyFactory的getProxy方法,把 Invoker 转换为客户端需要的接口(如:HelloWorld)。
在这里插入图片描述

SPI机制

Service Provider Interface,可以帮助我们动态寻找服务/功能的实现。
具体原理:将接口的实现类放在配置文件中,我们在程序运行过程中读取配置文件,通过反射动态地加载实现类。

扩展 Dubbo 中的默认实现

SPI扩展实现 https://dubbo.apache.org/zh/docs/v2.7/dev/impls/
例如:负载均衡扩展 https://dubbo.apache.org/zh/docs/v2.7/dev/impls/load-balance/

Dubbo的微内核架构

Dubbo 采用 微内核(Microkernel) + 插件(Plugin) 模式,简单来说就是微内核架构。
微内核架构包含两类组件:核心系统(core system) 和 插件模块(plug-in modules)。
在这里插入图片描述
核心系统提供系统所需核心能力,插件模块可以扩展系统的功能。因此, 基于微内核架构的系统,非常易于扩展功能。
通常情况下,微核心都会采用 Factory、IoC、OSGi 等方式管理插件生命周期。Dubbo 不想依赖 Spring 等 IoC 容器,也不想自己造一个小的 IoC 容器(过度设计),因此采用了一种最简单的 Factory 方式管理插件 :JDK 标准的 SPI 扩展机制 (java.util.ServiceLoader)。

Dubbo的序列化协议

参考:https://dubbo.apache.org/zh/docs/v2.7/user/serialization/
在 Dubbo 中使用高效的 Java 序列化(Kryo 和 FST)。
序列化对于远程调用的响应速度、吞吐量、网络带宽消耗等同样也起着至关重要的作用,是我们提升分布式系统性能的最关键因素之一。

在dubbo RPC中,同时支持多种序列化方式,例如:
dubbo序列化:阿里尚未开发成熟的高效java序列化实现,阿里不建议在生产环境使用它
hessian2序列化:hessian是一种跨语言的高效二进制序列化方式。但这里实际不是原生的hessian2序列化,而是阿里修改过的hessian lite,它是dubbo RPC默认启用的序列化方式
json序列化:目前有两种实现,一种是采用的阿里的fastjson库,另一种是采用dubbo中自己实现的简单json库,但其实现都不是特别成熟,而且json这种文本序列化性能一般不如上面两种二进制序列化。
java序列化:主要是采用JDK自带的Java序列化实现,性能很不理想。
在通常情况下,这四种主要序列化方式的性能从上到下依次递减。

最近几年,各种新的高效序列化方式层出不穷,不断刷新序列化性能的上限,最典型的包括:
专门针对Java语言的:Kryo,FST等等
跨语言的:Protostuff,ProtoBuf,Thrift,Avro,MsgPack等等
这些序列化方式的性能多数都显著优于hessian2。

而dubbo RPC实际上完全是一种Java to Java的远程调用,其实没有必要采用跨语言的序列化方式。有鉴于此,我们为dubbo引入Kryo和FST这两种高效Java序列化实现,来逐步取代hessian2。
使用Kryo和FST非常简单,只需要在dubbo RPC的XML配置中添加一个属性即可。

序列化性能分析与测试:
在做性能分析和测试的时候我们并不单独处理每种序列化方式,而是把它们放到dubbo RPC中加以对比,因为这样更有现实意义。
在这里插入图片描述
Dubbo RPC中不同序列化响应时间和吞吐量对比:
在这里插入图片描述

Dubbo提供的负载均衡策略

参考:https://dubbo.apache.org/zh/docs/v2.7/dev/source/loadbalance/
随机负载均衡:
是加权随机算法的具体实现。设定每个服务器对应的权重,假设权重为[5,3,2],总区间为[0-10),A机器对应的范围[0,5),B机器[5,8),C机器[8,10),然后每次调用时,通过一个随机数生成器生成一个[0,10)之间的数字,落在哪个范围内,就调用哪一台机器的方法。只要随机数生成器的分布性足够好,每个服务器被选中的概率就接近于其权重比例。
最小活跃数负载均衡:
活跃调用数越小,表明该服务提供者效率越高,单位时间内可处理更多的请求。此时应优先将请求分配给该服务提供者。
一致性 hash:
加权轮询:
经过加权后,每台服务器能够得到的请求数比例,接近或等于他们的权重比。比如服务器 A、B、C 权重比为 5:2:1。那么在8次请求中,服务器 A 将收到其中的5次请求,服务器 B 会收到其中的2次请求,服务器 C 则收到其中的1次请求。

Dubbo3新特性

参考:https://dubbo.apache.org/zh/docs/new-in-dubbo3/
服务发现模型:
相比于 2.x 版本中的基于接口粒度的服务发现机制,3.x 引入了全新的基于应用粒度的服务发现机制。
下一代RPC通信协议:
全新的 RPC 通信协议 – Triple。一句话概括 Triple:它是基于 HTTP/2 上构建的 RPC 协议,完全兼容 gRPC,并在此基础上扩展出了更丰富的语义。
面向云原生:
Dubbo3 构建的业务应用可直接部署在 VM、Container、Kubernetes 等平台。
服务发现层面,Dubbo3 支持与 Kubernetes Native Service 的融合,目前限于 Headless Service。
Dubbo3 规划了两种形态的 Service Mesh 方案,在不同的业务场景、不同的迁移阶段、不同的基础设施保障情况下,Dubbo 都会有 Mesh 方案可供选择, 而这进一步的都可以通过统一的控制面进行治理。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值