目录
Dubbo服务治理易用性的原理:
URL地址数据划分:
Dubbo接口级服务发现---易用性的代价
Proposal,适应云原生、更大规模集群的服务发现类型。
Dubbo3应用级服务发现---基本原理
Dubbo负载均衡机制
常规负载均衡算法
负载均衡策略:
Weighted Random
RoundRobin
LeastActive
ShortestResponse
配置方式:
自适应负载均衡与服务柔性
整体介绍:
P2C算法原理介绍:
Dubbo服务治理易用性的原理:
- 地址发现聚合Key==RPC粒度服务
- 注册中心同步的地址包含地址、元数据与配置
- 得益于1与2,Dubbo可以支持应用、RPC、方法粒度的服务治理
URL地址数据划分:
- 首先是实例可访问地址,主要信息包含ip port,是消费端将基于这条数据生成tcp网络连接,作为后续RPC数据的传输载体
- 其次是RPC元数据,元数据用于定义和描述一次RPC请求,一方面表明这条地址数据是与某条具体的RPC服务有关的,它的版本号,分组以及方法相关信息,另一方面表明。
- 下一部分是RPC配置数据,部分配置用于控制RPC调用的行为,还有一部分配置用于同步Provider进程实例的状态,典型的如超时时间,数据编码的序列化方式等。
- 最后一部分是自定义的元数据,这部分内容区别于以上框架预定义的各项配置,给了用户更大的灵活性,用户可任意扩展并添加自定义元数据,以进一步丰富实例状态。
以上就是Dubbo2在易用性、服务治理功能性、可扩展性上强于很多服务框架的真正原因。
Dubbo接口级服务发现---易用性的代价
一个事物总是有其两面性,Dubbo2地址模型带来易用性和强大功能的同时,也给整个架构的水平可扩展性带来了一些限制。这个问题在普通规模的微服务集群下是完全感知不到的,而随着集群规模的增长,当整个集群内应用、机器达到一定数量时,整个集群内的各个组件才开始遇到规模瓶颈。在总结 包括阿里巴巴、工商银行等多个大厂用户在生产环境特点后,我们总结出以下两点突出问题。
- 首先,注册中心集群容量达到上限阈值。由于所有的URL地址数据都被发送到注册中心,注册中心的存储容量达到上限,推送效率也随着下降。
- 而在消费端这一侧,Dubbo2框架常驻内存已超40%,每次地址推送带来的CPU等资源消耗率也非常高 ,影响正常的业务调用。
- 青色部分,假设这里有一个普通的Dubbo Provider应用,该应用内部定义有10个RPC Service,应用被部署在100个机器实例上,这个应用在集群中产生的数据量将会是“Service数*机器实例数”,也就是10*100=1000条,数据被从两个维度放大了。
-
- 从地址角度:100条唯一的实例地址,被放大了10倍
- 从服务角度:10条唯一的服务元数据,被放大100倍
Proposal,适应云原生、更大规模集群的服务发现类型。
问题点:
- 如何重新组织数据(地址、RPC元数据、RPC配置),避免冗余数据的出现
- 如何在保留易用性的同时,在地址发现层面(注册中心数据格式)与其他微服务体系打通
Dubbo3应用级服务发现---基本原理
Dubbo3的应用级服务发现方案设计本质上就是围绕以上两个问题展开。其基本思路是:地址发现链路上的聚合元素也就是我们之前提到的key由服务调整为应用,这也是其名称叫做应用级服务发现的由来;另外,通过注册中心同步的数据内容上做了大幅精简,只保留最核心的IP、port地址数据。
升级后的变化:
首先:在Provider实例这一侧,相比于之前每个RPC Service注册一条地址数据,一个Provider实例只会注册一条地址到注册中心。
其次,在注册中心这一侧,地址以应用名为粒度做聚合,应用名节点下是精简过后的Provider实例地址。
Dubbo3引入了一个内置MetadataService元数据服务,由中心化推送为Customer到Provider的点对点拉取,在这个模式下,元数据传输的数据量将不在一个问题,因此可以在元数据中扩展出更多的参数,暴露出更多的治理数据。
消费端Cusumer的地址订阅行为,消费端从分两步读取地址数据,首先是从注册中心收到精简后的地址,随后通过调用MetadataService元数据服务,读取对端的元数据信息、在收到这两部分数据之后,消费端会完成地址数据的聚合,最终在运行态还原出类似Dubbo2的URL地址格式,因此从最终结果而言,应用级地址模型同时兼顾了地址传输层面的性能与运行层面的功能性。
Dubbo负载均衡机制
常规负载均衡算法
在集群负载均衡时,Dubbo提供了多种均衡策略,缺省为weighted random基于权重的随机负载均衡策略。
具体实现上,Dubbo提供的是客户端负载均衡,即由Consumer通过负载均衡算法得出需要将请求提交到那个Provider实例。
负载均衡策略:
目前Dubbo内置如下负载均衡算法,可通过调整配置项进行启用
Weighted Random
加权机制,按权重设置随机概率。
在一个截面上碰撞概率高,但是调用量越大分布越均匀,而且按概率使用权重后也比较均匀,有利于动态调整提供者权重。
缺点:存在慢的提供者累计请求的问题,比如:第二台机器很慢,但是没有宕机,当前请求调用到第二台时就卡了。时间长了之后,所有的请求都卡在第二台机器上面了。
RoundRobin
加权轮询,按公约后的权重设置轮询比例,循环调用节点。
缺点:同样存在慢的提供者累计请求的问题
加权轮询过程中,如果某节点权重过大,会存在某段时间内调用过于集中的问题。
LeastActive
加权最少活跃调用优先,活跃数越低,越优先调用,相同活跃数的进行加权随机处理。活跃数指调用前后技术差(针对特定提供者,请求发送数-响应返回数),表示特定提供者的任务堆积量,活跃数越低,代表提供者处理能力越强。
慢的提供者收到更少请求,因为越慢的提供者的调用前后计数差会越大,相对的,处理能力越强的节点,处理更多的请求。
ShortestResponse
加权最短响应优先,在最近一个滑动窗口中,响应时间越短,越优先调用,相同响应时间的进行加权随机。
使得响应时间越快的提供者,处理更多的请求
缺点:可能会造成流量过于集中于高性能节点的问题
这里的响应时间=某个提供者在窗口时间内的平均响应时间,窗口时间默认是30s
ConsistentHash
一致性Hash,相同参数的请求总是发到同一提供者
当某一台提供者宕机时,原本提供者的请求,基于虚拟节点,平摊到其他提供者,不会引起剧烈变动。
缺省只对第一个参数Hash,如果要修改,需要配置:<dubbo:parameter
key="hash.arguments" value="0,1" />
缺省用160份虚拟节点,如果要修改,请配置置 <dubbo:parameter
key="hash.nodes" value="320" />
配置方式:
Dubbo支持在服务提供者一侧配置默认的负载均衡,这样所有消费者都默认使用提供者指定的负载均衡策略,消费者可以自己配置要使用的负载均衡策略,如果没有任何配置,则默认使用随机负载均衡策略。
同一个应用内支持配置不同的服务使用不同的负载均衡策略,支持同一服务的不同方法配置不同的负载均衡策略。
自适应负载均衡与服务柔性
整体介绍:
所谓的“柔性服务”主要是指consumer端的负载均衡和provider端的限流两个功能,在这之前dubbo版本中,负载均衡部分更多的考虑是公平性原则,即consumer端尽可能平等的从provider中做出选择,在某些情况下表现并不够理想。而限流部分只提供了静态的限流方案,需要用户对provider端设置静态的最大并发值,然而该值的合理选取对用户来讲并不容易。
P2C算法原理介绍:
- 对于每次调用,从可用的Provider列表中做两次随机选择,选出两个节点providerA和providerB.
- 比较providerA和providerB两个节点,选择其“当前正在 处理的连接数”较小的那个节点。