# 为何 Ribbon 可以做到负载均衡(原理)?

image.png 发送请求:image.png 继续 debug 会进入到 LoadBalancerInterceptor 拦截器中,我们会发现在拦截请求中实质上是获取了 URI,获取了主机名称,后将主机名称传给了 RibbonLoadBalanceIacerClient, 负载均衡客户端会继续执行image.png 之后进入到 execute 方法中,通过服务 ID,会在 Eureka 中找到 ID 相同的服务封装成 List。(RibbonLoadBalancerClient)getLoadBalancer 是在根据服务名称找 Eureka 的服务名称来拉取服务的,继续进入 getServer 方法中,image.pngimage.png 到这里一步,我们已经拉取到服务列表了,这样我们就可以开始做负载均衡了,我们可以看到使用了一个叫 rule 的 choose 方法来选择image.pngrule 是什么呢?image.png 通过 IRule 来决定选择负载均衡image.png 执行完成 rule 的 choose 之后,我们就找到了这个服务的 ip 和端口号了image.png

实质上,我们的请求会被一个叫做 LoadBalanceInterceptor 负载均衡拦截器拦截,后将服务的名称交给 RibbonLoadBalcaneClient,然后将 url 的服务 ID 交给 DynamicServiceListLoadBalance 去拉取服务信息,然后通过 IRule 来做负载均衡。image.png

# 配置 Ribbon 负载均衡

# Ribbon 负载均衡策略

Ribbon 的负载均衡规则是一个叫做 IRule 的接口来定义的,每一个子接口都是一种规则:image.png

# 负载均衡策略

内置负载均衡规则类 规则描述
RoundRobinRule 简单轮询服务列表来选择服务器。它是 Ribbon 默认的负载均衡规则。
AvailabilityFilteringRule 对以下两种服务器进行忽略:(1)在默认情况下,这台服务器如果 3 次连接失败,这台服务器就会被设置为 “短路” 状态。短路状态将持续 30 秒,如果再次连接失败,短路的持续时间就会几何级地增加。(2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了 AvailabilityFilteringRule 规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的..ActiveConnectionsLimit 属性进行配置。
WeightedResponseTimeRule 为每一个服务器赋予一个权重值。服务器响应时间越长,这个服务器的权重就越小。这个规则会随机选择服务器,这个权重值会影响服务器的选择。
ZoneAvoidanceRule 以区域可用的服务器为基础进行服务器的选择。使用 Zone 对服务器进行分类,这个 Zone 可以理解为一个机房、一个机架等。而后再对 Zone 内的多个服务做轮询。
BestAvailableRule 忽略那些短路的服务器,并选择并发数较低的服务器。
RandomRule 随机选择一个可用的服务器。
RetryRule 重试机制的选择逻辑

这样我们完全可以自己配置一个 bean 来实现自定义负载均衡策略。

# 配置方式:

# 全局配置:

@Bean
public IRule randomRule(){
    return new RandomRule();
}

这样配置,会导致我们选择任何服务者都是使用我们自己配置的 RandomRule 方式来选择服务的。即选择调用任何服务接口都是随机的。配置文件方式(非全局,需自己选择):

userservice:  # 服务名称
   ribbon:
     NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule  # 负载均衡规则
# 可配置其他的服务负载均衡规则

小提示:我们自己手动配置的 bean 会注入到 Spring 容器中,这样在给其他类添加属性 bean 时会将 Spring 容器中的 bean 注入到该对象上去。所以我们的配置的 bean 才会生效,走我们自己配置信息。

# Ribbon 默认是懒加载模式:

默认第一次请求的时候,才会去创建 LoadBalanceClient, 请求时间会很长。

# 饥饿加载

我们配置饥饿加载会在项目启动时创建,降低第一次访问的耗时,我们可以通过下面的配置来开启饥饿加载:

ribbon:
  eager-load:
    enabled: true # 开启饥饿加载
    clients: userservice  # 我们针对那个服务做的饥饿加载
ribbon:
  eager-load:
    enabled: true # 开启饥饿加载
    clients:  # 配置针对多个
      - userservice
      - xxservice

# 稍作总结:

1、Ribbon 负载均衡规则

  • 默认接口是 IRule
  • 默认选择是 ZoneAvoidanceRule, 根据 zone 选择服务列表,然后轮询

2、负载均衡自定义方式

  • 代码方式:配置灵活,但修改时需要重新打包发布
  • 配置方式:直观,方便,无需重新打包发布,但是无法做到全局配置

3、饥饿加载

  • 开启饥饿加载
  • 指定饥饿加载的微服务名称