Dubbo负载均衡、协议

转载:http://dubbo.apache.org/zh-cn/blog/dubbo-loadbalance.html

背景

Dubbo是一个分布式服务框架,能避免单点故障和支持服务的横向扩容。一个服务通常会部署多个实例。如何从多个服务 Provider 组成的集群中挑选出一个进行调用,就涉及到一个负载均衡的策略。

几个概念

在讨论负载均衡之前,我想先解释一下这3个概念。

  1. 负载均衡
  2. 集群容错
  3. 服务路由

这3个概念容易混淆。他们都描述了怎么从多个 Provider 中选择一个来进行调用。那他们到底有什么区别呢?下面我来举一个简单的例子,把这几个概念阐述清楚吧。

有一个Dubbo的用户服务,在北京部署了10个,在上海部署了20个。一个杭州的服务消费方发起了一次调用,然后发生了以下的事情:

  1. 根据配置的路由规则,如果杭州发起的调用,会路由到比较近的上海的20个 Provider。
  2. 根据配置的随机负载均衡策略,在20个 Provider 中随机选择了一个来调用,假设随机到了第7个 Provider。
  3. 结果调用第7个 Provider 失败了。
  4. 根据配置的Failover集群容错模式,重试其他服务器。
  5. 重试了第13个 Provider,调用成功。

上面的第1,2,4步骤就分别对应了路由,负载均衡和集群容错。 Dubbo中,先通过路由,从多个 Provider 中按照路由规则,选出一个子集。再根据负载均衡从子集中选出一个 Provider 进行本次调用。如果调用失败了,根据集群容错策略,进行重试或定时重发或快速失败等。 可以看到Dubbo中的路由,负载均衡和集群容错发生在一次RPC调用的不同阶段。最先是路由,然后是负载均衡,最后是集群容错。 本文档只讨论负载均衡,路由和集群容错在其他的文档中进行说明。

Dubbo内置负载均衡策略

Dubbo内置了4种负载均衡策略:

  1. Random LoadBalance:  随机负载均衡。随机的选择一个。是Dubbo的默认负载均衡策略。
  2. RoundRobin LoadBalance: 轮询负载均衡。轮询选择一个。
  3. LeastActive LoadBalance: 最少活跃调用数,相同活跃数的随机。活跃数指调用前后计数差。使慢的 Provider 收到更少请求,因为越慢的 Provider 的调用前后计数差会越大。
  4. ConsistentHash LoadBalance: 一致性哈希负载均衡。相同参数的请求总是落在同一台机器上。

1.随机负载均衡(默认)

顾名思义,随机负载均衡策略就是从多个 Provider 中随机选择一个。但是 Dubbo 中的随机负载均衡有一个权重的概念,即按照权重设置随机概率。比如说,有10个 Provider,并不是说,每个 Provider 的概率都是一样的,而是要结合这10个 Provider 的权重来分配概率

Dubbo中,可以对 Provider 设置权重。比如机器性能好的,可以设置大一点的权重,性能差的,可以设置小一点的权重。权重会对负载均衡产生影响。可以在Dubbo Admin中对 Provider 进行权重的设置。

基于权重的负载均衡算法

随机策略会先判断所有的 Invoker 的权重是不是一样的,如果都是一样的,那么处理就比较简单了。使用random.nexInt(length)就可以随机生成一个 Invoker 的序号,根据序号选择对应的 Invoker 。如果没有在Dubbo Admin中对服务 Provider 设置权重,那么所有的 Invoker 的权重就是一样的,默认是100。 如果权重不一样,那就需要结合权重来设置随机概率了。算法大概如下: 假如有4个 Invoker。

A,B,C和D总的权重是10 + 20 + 20 + 30 = 80。将80个数分布在如下的图中:

上面的图中一共有4块区域,长度分别是A,B,C和D的权重。使用random.nextInt(10 + 20 + 20 + 30),从80个数中随机选择一个。然后再判断该数分布在哪个区域。比如,如果随机到37,37是分布在C区域的,那么就选择 Invoker C。15是在B区域,54是在D区域。

2.轮询负载均衡

轮询负载均衡,就是依次的调用所有的 Provider。和随机负载均衡策略一样,轮询负载均衡策略也有权重的概念。轮询负载均衡算法可以让RPC调用严格按照我们设置的比例来分配。不管是少量的调用还是大量的调用。但是轮询负载均衡算法也有不足的地方,存在慢的 Provider 累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上,导致整个系统变慢。

3.最少活跃调用数负载均衡

这个解释好像说的不是太明白。目的是让更慢的机器收到更少的请求。举个例子:每个服务维护一个活跃数计数器。当A机器开始处理请求,该计数器加1,此时A还未处理完成。若处理完毕则计数器减1。而B机器接受到请求后很快处理完毕。那么A,B的活跃数分别是1,0。当又产生了一个新的请求,则选择B机器去执行(B活跃数最小),这样使慢的机器A收到少的请求。

4.一致性Hash算法

使用一致性 Hash 算法,让相同参数的请求总是发到同一 Provider。 当某一台 Provider 崩溃时,原本发往该 Provider 的请求,基于虚拟节点,平摊到其它 Provider,不会引起剧烈变动。

一致性Hash算法可以和缓存机制配合起来使用。比如有一个服务getUserInfo(String userId)。设置了Hash算法后,相同的userId的调用,都会发送到同一个 Provider。这个 Provider 上可以把用户数据在内存中进行缓存,减少访问数据库或分布式缓存的次数。如果业务上允许这部分数据有一段时间的不一致,可以考虑这种做法。减少对数据库,缓存等中间件的依赖和访问次数,同时减少了网络IO操作,提高系统性能。

负载均衡配置

如果不指定负载均衡,默认使用随机负载均衡。我们也可以根据自己的需要,显式指定一个负载均衡。 可以在多个地方类来配置负载均衡,比如 Provider 端,Consumer端,服务级别,方法级别等。

服务端服务级别

<dubbo:service interface="..." loadbalance="roundrobin" />

该服务的所有方法都使用roundrobin负载均衡。

客户端服务级别

<dubbo:reference interface="..." loadbalance="roundrobin" />

该服务的所有方法都使用roundrobin负载均衡。

服务端方法级别

<dubbo:service interface="...">
    <dubbo:method name="hello" loadbalance="roundrobin"/>
</dubbo:service>

只有该服务的hello方法使用roundrobin负载均衡。

客户端方法级别

<dubbo:reference interface="...">
    <dubbo:method name="hello" loadbalance="roundrobin"/>
</dubbo:reference>

只有该服务的hello方法使用roundrobin负载均衡。

和Dubbo其他的配置类似,多个配置是有覆盖关系的:

  1. 方法级优先,接口级次之,全局配置再次之。
  2. 如果级别一样,则消费方优先,提供方次之。

Dubbo支持协议:

Dubbo支持dubbo、rmi、hessian、http、webservice、thrift、redis等多种协议,但是Dubbo官网是推荐我们使用Dubbo协议。
1、dubbo 协议 (默认)

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

缺省协议,使用基于mina1.1.7+hessian3.2.1的tbremoting交互。

    连接个数:单连接
    连接方式:长连接
    传输协议:TCP
    传输方式:NIO异步传输
    序列化:Hessian 二进制序列化
    适用范围:传入传出参数数据包较小(建议小于100K),消费者比提供者个数多,单一消费者无法压满提供者,尽量不要用dubbo协议传输大文件或超大字符串。
    适用场景:常规远程服务方法调用

2、RMI 协议

1、RMI协议采用JDK标准的java.rmi.*实现,采用阻塞式短连接和JDK标准序列化方式 。

    连接个数:多连接
    连接方式:短连接
    传输协议:TCP
    传输方式:同步传输
    序列化:Java标准二进制序列化
    适用范围:传入传出参数数据包大小混合,消费者与提供者个数差不多,可传文件。
    适用场景:常规远程服务方法调用,与原生RMI服务互操作

3、hessian 协议

Hessian 协议用于集成 Hessian 的服务,Hessian 底层采用 Http 通讯,采用 Servlet 暴露服务,Dubbo 缺省内嵌 Jetty 作为服务器实现。

Dubbo 的 Hessian 协议可以和原生 Hessian 服务互操作,即:

1、提供者用 Dubbo 的 Hessian 协议暴露服务,消费者直接用标准 Hessian 接口调用
2、 或者提供方用标准 Hessian 暴露服务,消费方用 Dubbo 的 Hessian 协议调用。

    连接个数:多连接
    连接方式:短连接
    传输协议:HTTP
    传输方式:同步传输
    序列化:Hessian二进制序列化
    适用范围:传入传出参数数据包较大,提供者比消费者个数多,提供者压力较大,可传文件。
    适用场景:页面传输,文件传输,或与原生hessian服务互操作

4、http 协议

基于http表单的远程调用协议。

    连接个数:多连接
    连接方式:短连接
    传输协议:HTTP
    传输方式:同步传输
    序列化:表单序列化
    适用范围:传入传出参数数据包大小混合,提供者比消费者个数多,可用浏览器查看,可用表单或URL传入参数,暂不支持传文件。
    适用场景:需同时给应用程序和浏览器JS使用的服务。

5、webservice 协议

基于 WebService 的远程调用协议,基于 Apache CXF的 frontend-simple 和 transports-http 实现。

可以和原生 WebService 服务互操作,即:

1、提供者用 Dubbo 的 WebService 协议暴露服务,消费者直接用标准 WebService 接口调用。
2、或者提供方用标准 WebService 暴露服务,消费方用 Dubbo 的 WebService 协议调用。

    连接个数:多连接
    连接方式:短连接
    传输协议:HTTP
    传输方式:同步传输
    序列化:SOAP文本序列化
    适用场景:系统集成,跨语言调用
 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值