概念

dubbo负载均衡官网介绍:
中文官网介绍的非常的详细
https://dubbo.apache.org/zh/docs/v2.7/user/examples/loadbalance/

四种策略

Random LoadBalance

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

    RoundRobin LoadBalance

  • 轮询,按公约后的权重设置轮询比率。

  • 存在慢的提供者累积请求的问题,比如:第二台机器很慢,但没挂,当请求调到第二台时就卡在那,久而久之,所有请求都卡在调到第二台上。

    LeastActive LoadBalance

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

    假如说A B C三个服务提供者, 每个服务都记录自己当前有几个请求正在处理,
    假如说A服务现在有三个请求正在处理, B服务有一个请求正在处理 ,C服务有四个请求正在处理. 那么consumer发起调用的时候会调用B服务,因为B服务正在处理的请求最少
    如果A B C 这三个provider ,A和B服务有1个正在处理的请求,C服务有2个正在处理的请求. 那么A和B服务都是最小活跃调用数,而且两个数都是一样的,都是1,那么consumer就对A和B这两个最小活跃调用数随机找一台出来进行调用,.

    消费者是怎么知道每个provider服务正在执行的最小请求数呢?

  1. 消费者会缓存所调用服务的所有提供者,这个是从注册中心去查询的
  2. 比如记为p1、p2、p3三个服务提供者对象,每个提供者对象内都有一个提供者服务url属性,一个属性记为active,默认位0

  3. 消费者在第一次调用次服务时,如果负载均衡策略是leastactive,因为是第一次调用,三台服务的提供者都是0,那么直接就随机找出一台进行调用否则的话消费者端会判断缓存的所有服务提供者的active,选择最小的,如果都相同,则随机.

  4. 选出某一个服务提供者后,假设服务是p2服务,Dubbo就会对p2服务的active属性进行+1操作,然后再发出请求调用该服务
  5. 消费端收到响应结果后,对p2服务的active属性-1操作
  6. 这样服务的消费端就完成了对某个服务提供者当前活跃调用数进行了统计,并且并不影响服务调用的性能

ConsistentHash LoadBalance

  • 一致性 Hash,相同参数的请求总是发到同一提供者。

  • 当某一台提供者挂时,原本发往该提供者的请求,基于虚拟节点,平摊到其它提供者,不会引起剧烈变动。

使用

负载均衡可以在服务发起者服务定义的时候配,也可以在消费者那里配置.

如果在消费端和服务端同时都配置了负载均衡策略,以消费端的配置为准(服务端的配置不生效)。

在生产者配置

类上面的@Service注解有个loadbalance属性

  1. //loadbalance = "roundrobin" 配置负载均衡算法,默认是随机,roundrobin是轮训
  2. @Service(version = "default" ,loadbalance = "roundrobin")
  3. public class DefaultDemoService implements DemoService {
  4. @Override
  5. public String sayHello(String name) {
  6. System.out.println("执行了服务" + name);
  7. URL url = RpcContext.getContext().getUrl();
  8. return String.format("%s:%s, Hello, %s", url.getProtocol(), url.getPort(), name); // 正常访问
  9. }
  10. }

在消费者配置

引用dobbo接口的@Reference 注解有个loadbalance属性

  1. @SpringBootApplication
  2. public class DubboConsumerDemo {
  3. //loadbalance 负载均衡配置,默认是随机,roundrobin是轮训
  4. @Reference(version = "default",loadbalance = "roundrobin")
  5. private DemoService demoService;
  6. public static void main(String[] args) {
  7. ConfigurableApplicationContext context = SpringApplication.run(DubboConsumerDemo.class);
  8. DemoService demoService = context.getBean(DemoService.class);
  9. System.out.println((demoService.sayHello("周瑜")));
  10. }
  11. }

代码地址和测试

https://gitee.com/zjj19941/ZJJ_Dubbo.git

下载下来看load-balancing项目,
然后先启动两个provider ,注意要修改provider的配置文件的server.port和dubbo.protocol.port 这两个属性,不要重复了,不然会出现端口占用.

然后看一下zookeeper发现有两个provider.

image.png

然后执行consumer类的DubboConsumerDemo方法,注意观察控制台,发现被随机调用了.

  1. dubbo20881, Hello, 周瑜
  2. dubbo20880, Hello, 周瑜
  3. dubbo20881, Hello, 周瑜
  4. dubbo20880, Hello, 周瑜
  5. dubbo20881, Hello, 周瑜
  6. dubbo20880, Hello, 周瑜
  7. dubbo20881, Hello, 周瑜
  8. dubbo20880, Hello, 周瑜
  9. dubbo20881, Hello, 周瑜
  10. dubbo20880, Hello, 周瑜
  11. dubbo20881, Hello, 周瑜
  12. dubbo20880, Hello, 周瑜
  13. dubbo20881, Hello, 周瑜

观察provider控制台,也发现被调用了,这个控制台结果就不贴上来了.