# 为何 Ribbon 可以做到负载均衡(原理)?
发送请求:
继续 debug 会进入到 LoadBalancerInterceptor 拦截器中,我们会发现在拦截请求中实质上是获取了 URI,获取了主机名称,后将主机名称传给了 RibbonLoadBalanceIacerClient, 负载均衡客户端会继续执行
之后进入到 execute 方法中,通过服务 ID,会在 Eureka 中找到 ID 相同的服务封装成 List。(RibbonLoadBalancerClient)getLoadBalancer 是在根据服务名称找 Eureka 的服务名称来拉取服务的,继续进入 getServer 方法中,
到这里一步,我们已经拉取到服务列表了,这样我们就可以开始做负载均衡了,我们可以看到使用了一个叫 rule 的 choose 方法来选择
rule 是什么呢?
通过 IRule 来决定选择负载均衡
执行完成 rule 的 choose 之后,我们就找到了这个服务的 ip 和端口号了
实质上,我们的请求会被一个叫做 LoadBalanceInterceptor 负载均衡拦截器拦截,后将服务的名称交给 RibbonLoadBalcaneClient,然后将 url 的服务 ID 交给 DynamicServiceListLoadBalance 去拉取服务信息,然后通过 IRule 来做负载均衡。
# 配置 Ribbon 负载均衡
# Ribbon 负载均衡策略
Ribbon 的负载均衡规则是一个叫做 IRule 的接口来定义的,每一个子接口都是一种规则:
# 负载均衡策略
| 内置负载均衡规则类 | 规则描述 |
|---|---|
| RoundRobinRule | 简单轮询服务列表来选择服务器。它是 Ribbon 默认的负载均衡规则。 |
| AvailabilityFilteringRule | 对以下两种服务器进行忽略:(1)在默认情况下,这台服务器如果 3 次连接失败,这台服务器就会被设置为 “短路” 状态。短路状态将持续 30 秒,如果再次连接失败,短路的持续时间就会几何级地增加。(2)并发数过高的服务器。如果一个服务器的并发连接数过高,配置了 AvailabilityFilteringRule 规则的客户端也会将其忽略。并发连接数的上限,可以由客户端的 |
| 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、饥饿加载
- 开启饥饿加载
- 指定饥饿加载的微服务名称