Client Side Load Balancer: Ribbon
基本使用
- 被服务消费者使用,负载均衡的调用服务提供者
 
- Zuul基于Ribbon请求转发
 
- Fegin基于Ribbon调用
 
1 2 3 4 5 6 7 8
   | @Bean @LoadBalanced public RestTemplate restTemplate() { 	return new RestTemplate(); }
  之后在使用restTemplate.getForObject("http://eureka-client-provider/dc", String.class);时 会采用默认配置负载均衡调用该服务的多个实例,默认轮询调用每个服务实例
   | 
 
主要类
- RibbonClientConfiguration: 默认的RibbonClient配置类
 
- IRule:为LoadBalancer定义的规则接口,作为负载均衡的策略,常用有轮询,随机,基于时间响应等,可查看它的实现类列表,如:RandomRule,RoundRobinRule
 
- IPing: 判断server是否up, 默认实现DummyPing,与eureka结合时,为NIWSDiscoveryPing,代理eureka去决定一个server是否up,保持心跳,维护客户端侧可用的服务器清单
 
1 2 3 4 5 6 7 8 9
   | Spring Cloud Netflix provides the following beans by default for ribbon (BeanType beanName: ClassName):
  IClientConfig ribbonClientConfig: DefaultClientConfigImpl IRule ribbonRule: ZoneAvoidanceRule IPing ribbonPing: DummyPing ServerList<Server> ribbonServerList: ConfigurationBasedServerList ServerListFilter<Server> ribbonServerListFilter: ZonePreferenceServerListFilter ILoadBalancer ribbonLoadBalancer: ZoneAwareLoadBalancer ServerListUpdater ribbonServerListUpdater: PollingServerListUpdater
   | 
 
自定义对某个服务的Ribbon Client配置
1 2 3 4 5 6 7 8 9 10 11
   | 1. 其中模仿RibbonClientConfiguration类覆盖相应的
  @Configuration public class CustomRibbonClientConfiguration {
      // 配置负载选取规则,随机选择一个服务调用     @Bean     public IRule ribbonRule() {         return new RandomRule();     } }
   | 
 
1 2 3 4
   | 2. 启动类上配置如下    对eureka-client-provider服务使用1步中自定义的配置类CustomRibbonClientConfiguration
  @RibbonClient(name = "eureka-client-provider", configuration = CustomRibbonClientConfiguration.class)
   | 
 
- 默认的均衡选取策略为轮询
 
- 此时Ribbon策略配置由RibbonClientConfiguration和CustomRibbonClientConfiguration共同组成
 
1 2 3 4 5
   | Note:      尽量避免1中的配置类被启动类中的SpringBootApplication注解中的ComponentScan注解扫描到,如果自定义RibbonClient被主类扫描,该配置将在parent context,将对所有的服务的调用生效该配置。 Solve:     1. 避免1中的配置类和启动类在一个包下,即启动类不会扫描到该配置类     2. 如果在启动类的扫描范围内,将该配置类从@ComponentScan中排除,实现如下
   | 
 
- 配置类在启动类扫描范围内如下解决方案
1 2 3 4 5 6 7 8 9 10 11 12 13
   | 1. 声明一个注解
  /**  * 添加该注解的类将从主类扫描中排除  * Created by fuyi on 2018/1/13.  */ public @interface ExculdeFromComponentScan { }
  2. 在启动类上添加如下 @ComponentScan(excludeFilters = {@ComponentScan.Filter(type = FilterType.ANNOTATION, value = ExculdeFromComponentScan.class)})
  3. 在需要排除的类上添加@ExculdeFromComponentScan注解
   | 
 
- 可使用如下代码测试负载均衡策略
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
   | @RestController public class DcController {
      @Autowired     private RestTemplate restTemplate;
      @Autowired     private LoadBalancerClient loadBalancerClient;
      @GetMapping("/consumer")     public String dc() {
          String url = "http://eureka-client-provider/dc";
          //使用restTemplate请求数据         return restTemplate.getForObject(url, String.class);     }
 
      @GetMapping("/loadBal")     public void loadBal() {         ServiceInstance serviceInstance = loadBalancerClient.choose("eureka-client-provider");         System.out.println("serviceId : " + serviceInstance.getServiceId() + ",port : " + serviceInstance.getPort() + ",Uri : " + serviceInstance.getUri());
          ServiceInstance serviceInstance2 = loadBalancerClient.choose("eureka-client-provider2");         System.out.println("serviceId : " + serviceInstance2.getServiceId() + ",port : " + serviceInstance2.getPort() + ",Uri : " + serviceInstance2.getUri());
      } }
   | 
 
自定义对所有Ribbon Client的默认配置
- 在启动类上使用RibbonClients,为它的defaultConfiguration属性设置一个自定义的配置类
 
1
   | @RibbonClients(defaultConfiguration = CustomRibbonClientConfiguration.class)
   | 
 
使用配置文件Customizing the Ribbon Client
- 对eureka-client-provider服务均衡规则采用RandomRule,如下配置
 
1 2 3
   | eureka-client-provider:   ribbon:     NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
   | 
 
各种配置优先级
官方文档只说明了  配置文件 > @RibbonClient自定义 > 默认配置, 经测试@RibbonClients为最高优先级配置,对所有Ribbon Client的配置
Ribbon with Eureka
- spring-cloud-starter-eureka包含spring-cloud-starter-ribbon
 
Ribbon without Eureka
- 不结合eureka 使用时,服务提供者的地址列表需自己配置,如下
1 2 3
   | stores:   ribbon:     listOfServers: example.com,google.com
   | 
 
- eureka在classpath下,但不想使用,可配置如下禁用
 
1 2 3
   | ribbon:   eureka:    enabled: false
   | 
 
Ribbon懒加载(Dalston.SR5文档新增)
- 每个ribbon client默认有相应的子application context被spring cloud维护的
 
- 默认被第一次请求时才被load
 
- 可配置如下,使该context在startup时被load
 
1 2 3 4
   | ribbon:   eager-load:     enabled: true     clients: eureka-client-provider2,eureka-client-provider
   | 
 
配置属性
1 2 3 4 5
   | 请求创建连接的超时时间 ribbon.ConnectTimeout=60000   请求处理的超时时间 ribbon.ReadTimeout=60000
   | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
   | <client>.ribbon.<key>=<value>,该client可采用服务名
  eureka-client-provider:   ribbon:     NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 配置均衡策略为随机选取一个实例访问     listOfServers: http://localhost:2001 #手动维护该服务提供者的实例清单      spring.cloud.loadbalancer.retry.enabled=true # 开启重试机制
  hystrix:   command:     default:       execution:         isolation:           thread:             timeoutInMilliseconds: 10000 #断路器的超时时间要大于Ribbon重试时间,不然不会触发重试
  eureka-client-provider.ribbon.ConnectionTimeout=250 eureka-client-provider.ribbon.ReadTimeout=1000 eureka-client-provider.ribbon.OkToRetryOnAllOperations=true #对所有操作请求都进行重试 eureka-client-provider.ribbon.MaxAutoRetriesNextServer=2 #切换实例的重试次数 eureka-client-provider.ribbon.MaxAutoRetries=1 #对当前实例的重试次数
  如果配置,当请求故障时,会在次尝试访问当前实例一次(MaxAutoRetries决定),如果不行,换一个实例访问,如果还不行,再换一次(MaxAutoRetriesNextServer决定),如果依然不行,返回失败信息。
 
 
   | 
 
结合Hystrix的超时设置
- Hystrix的超时时间要大于ribbon.connectionTimeout乘以重试次数
 
- 如:ribbon.connectionTimeout=1,重试次数3,则Hystrix的超时设置要大于3秒