Ribbon :一个基于 HTTP 和 TCP 的客户端的负载均衡工具,它是基于 Netflix Ribbon 实现的

  • Ribbon 几乎存在于每个 Spring Cloud 的微服务中,包括 Feign 提供的声明式服务调用也是基于该 Ribbon 实现的
  • Ribbon 默认提供很多种负载均衡算法,例如轮询、随机等,或者自定义负载均衡算法

负载均衡的常见方案:

  • 集中式负载均衡(服务器负载均衡):即在 consumer 和 provider 之间使用独立的负载均衡设施(可以是硬件,如F5,也可以是软件,如nginx),由该设施负责把访问请求通过某种策略转发至 provider
  • 进程内负载均衡(客户端负载均衡):将负载均衡逻辑集成到 consumer,consumer 从服务注册中心获知有哪些地址可用,然后自己再仓这些地址中选择出一个合适的 provider。Ribbon 属于后者,只是一个类库,集成于 consumer 进程,consumer 通过它来获取 provider 的地址

Ribbon 负载均衡策略

  • 轮询策略(默认):RoundRobinRule
    • 实现原理:每次都顺序取下一个 provider
  • 权重轮询策略:WeightedResponseTimeRule
    • 根据每个 provider 的响应时间分配一个权重,响应时间越长,权重越小,被选中的可能性越低
    • 原理:一开始为轮询策略,并开启一个计时器,每 30 秒收集一个每个 provider 的平均响应时间,当信息足够时,给每个 provider 附上一个权重,并按权重随机选择 provider,越高权重的 provider 会被高概率选中
  • 随机策略:RandomRule
    • 原理:从 provider 列表中随机选择一个
  • 最少并发数策略:BestAvailableRule
    • 原理:选择正在请求中的并发数最小的 provider,除非这个 provider 在熔断中
  • 重试策略:RetryRule
    • 原理:轮询策略的增强版,轮询策略服务不可用时不做处理,重试策略不可用时会重新尝试集群中的其他节点
  • 可用性敏感策略:AvailabilityFilteringRule
    • 实现原理:过滤掉性能差的 provider
      • 第一种:过滤掉在 Eureka 种处于一直连接失败的 provider
      • 第二种:过滤掉高并发(繁忙)的 provider
  • 区域性敏感策略:ZoneAvoidanceRule
    • 原理:
      • 以一个区域为单位考察可用性,对于不可用的区域整个丢弃,从剩下的区域种选可用的 provider
      • 如果这个 ip 区域内有一个或多个实例不可达或响应变慢,都会降低该 ip 区域内其他 ip 被选种的权重

Ribbon简单使用

在 Eureka 创建项目的基础上继续新增两个 service-provider:
根据前面一模一样的创建方式,修改端口即可

然后修改 service-consumer ,服务实现使用第二种复载均衡方式,顺便载控制台输出请求地址:

  1. @Service
  2. public class OrderServiceImpl implements OrderService {
  3. @Autowired
  4. private RestTemplate restTemplate;
  5. @Autowired
  6. private LoadBalancerClient loadBalancerClient; // Ribbon负载均衡
  7. @Override
  8. public Order selectOrderById(Integer id) {
  9. return new Order(id, "order-001", "中国", 123357D,
  10. selectProductListByDiscoveryClient());
  11. }
  12. private List<ProductDto> selectProductListByDiscoveryClient() {
  13. StringBuffer sb = null;
  14. // 根据服务名称获取一个服务
  15. ServiceInstance si = loadBalancerClient.choose("service-provider");
  16. if (null == si) {
  17. return null;
  18. }
  19. // 请求地址
  20. sb = new StringBuffer();
  21. sb.append("http://")
  22. .append(si.getHost())
  23. .append(":")
  24. .append(si.getPort())
  25. .append("/product/list");
  26. // 将请求的地址输出到控制台
  27. System.out.println(sb.toString());
  28. // 封装了返回数据
  29. ResponseEntity<List<ProductDto>> response = restTemplate.exchange(
  30. sb.toString(),
  31. HttpMethod.GET,
  32. null,
  33. new ParameterizedTypeReference<List<ProductDto>>() {});
  34. return response.getBody();
  35. }
  36. }

多次访问输出,可见默认使用负载策略是轮询:
image.png

Ribbon 负载均衡策略设置

1、Ribbon 全局负载均衡设置:在启动类或配置类中注入负载均衡策略对象,所有服务请求均使用该策略

  1. @Bean
  2. public RandomRule randomRule(){
  3. return new RandomRule();
  4. }

2、局部负载均衡设置:

  • 修改配置文件指定服务的负载均衡策略
  • 格式:服务应用名.ribbon.NFLoadBalancerRuleClassName
    1. # 负载均衡策略
    2. # service-provider 为调用的服务的名称
    3. service-provider:
    4. ribbon:
    5. NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule

Ribbon 点对点直连

点对点直连是指绕过注册中心,直接连接服务提供者获取服务,一般测试阶段使用比较多
1、添加依赖:在pom文件中引入Ribbon,需要注意的是如果pom中有Eureka的依赖,则需要去除Eureka的依赖

  1. <!-- netflix ribbon依赖 -->
  2. <dependency>
  3. <groupId>org.springframework.cloud</groupId>
  4. <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
  5. </dependency>

2、配置文件:配置文件中关闭 Eureka,添加直连的服务地址,如果不设置负载均衡策略默认使用轮询策略

  1. # 负载均衡策略:service-provider为调用的服务的名称
  2. service-provider:
  3. ribbon:
  4. NFLoadBalancerRulerClassName: com.netflix.loadbalancer.RandomRuler
  5. # 服务提供者的地址
  6. listOfServers: http://localhost:7000/product/list,http://localhost:7001/product/list,http://localhost:7002/product/list
  7. # 关闭Eureka,实现Ribbon点对点直连
  8. ribbon:
  9. eureka:
  10. enabled: false #false,关闭;true,开启