负载均衡器Ribbon
一、负载均衡简单了解
负载均衡,英文名称为Load Balance,其含义就是指将负载(工作任务)进行平衡、分摊到多个操作单元上进行运行,例如FTP服务器、Web服务器、企业核心应用服务器和其它主要任务服务器等,从而协同完成工作任务。
主流的负载均衡方案分为两种:一是集中式负载均衡,在消费者和提供者之间使用独立的代理方式进行负载,比如硬件的F5,或软件的Nginx;二是客户端根据自己的请求情况做负载均衡,比如Ribbon。
客户端与服务端的负载均衡
服务端负载均衡:
比如Nginx,先发送请求,然后通过负载均衡算法,在多个服务器之间进行访问,也就是所谓的在服务器端进行负载均衡算法分配。
客户端负载均衡:
比如Ribbon,spring cloud的客户端会有一个类似注册中心的服务器地址列表,在发送请求前通过负载均衡算法选择一个服务器,然后进行访问,也就是所谓的在客户端就进行负载均衡算法分配。
常见的负载均衡算法
-
随机:
随机选择服务 -
轮询:
默认实现方式,依次排队处理,轮流分配 -
加权轮询:
通过服务器性能,高性能低负载的服务器拥有更高的权重 -
地址Hash:
通过客户端请求的地址hash值取模映射进行服务器调度 -
最小连接数:
将任务分配给此时具有最小连接数的节点,因此它是动态负载均衡算法。一个节点收到一个任务后连接数就会加1,当节点故障时就将节点权值设置为0,不再给节点分配任务。
二、Spring Cloud Alibaba下Ribbon的使用
1. Ribbon负载均衡策略
IRule
是所有负载均衡策略的父接口,其中核心方法为choose,用来选择一个服务实例。
AbstractLoadBalancerRule
抽象类,通过ILoadBalancer从现有服务器列表中通过均衡策略选择服务器。
1.1 RandomRule(随机规则)
在现有服务器之间随机分配流量的负载平衡策略。通过生成一个不大于服务实例总数的随机数选择服务实例。
1.2 RoundRobinRule(轮询规则)
基本负载均衡策略。通过遍历服务实例,先获取实例总数,如果为0,则会警告负载均衡器没有可用的服务器(
No up servers available from load balancer:xxx
);如果实例数大于0,则会生成一个实例总数不断加1的数,取模后选取实例,如果连续十次都没取到实例,则会警告从负载均衡器尝试 10 次后没有可用的活动服务器(
No available alive servers after 10 tries from load balancer:xxx
)。
1.3 RetryRule(轮询+重试规则)
也是轮询机制,只是当轮询到一个已失效或者null的实例后,会在失效时间内进行不断重试,超时后返回null。
1.4 WeightedResponseTimeRule(权重规则)
会根据每个实例的运行情况计算出权重,默认情况下每30秒会计算一次,服务器的平均响应时间越短则权重越大,那么该实例被选中的概率也会越大。
1.5 BestAvailableRule(最佳可用规则)
此规则通常应与ServerListSubsetFilter一起使用,它对规则可见的服务器设置了限制。这确保了它只需要在少量服务器中找到最小的并发请求。此外,每个客户端将获得一个随机的服务器列表,避免了并发请求最低的服务器被大量客户端选择并立即不堪重负的问题。
1.6 ZoneAvoidanceRule(区域回避规则)
默认的规则,根据区域和可用性过滤服务器的规则,比如北京和上海的服务器,当你在北京访问时会优先请求北京的服务器。
1.7 AvailabilityFilteringRule(可用性过滤规则)
先过滤掉故障实例,再选择并发较小的实例。过滤规则:由于连续连接或读取失败而处于断路器跳闸状态,或
具有超过可配置限制的活动连接。
1.8 NacosRule(Nacos-权重)
Nacos扩展了一个自己的配置,配置中通过
spring.cloud.nacos.discovery.weight
设置权重大小。
2. 依赖
引入了spring-cloud-starter-alibaba-nacos-discovery就不必再引入ribbon,因为其中依赖了ribbon,点入可看到如下依赖:
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
<version>2.2.6.RELEASE</version>
<scope>compile</scope>
</dependency>
3. 代码中设置负载均衡策略
3.1 @LoadBalanced注解
用于标记要配置为使用 LoadBalancerClient 的 RestTemplate 或 WebClient bean 的注释。如下为标记RestTemplate,这样在使用restTemplate时会使用当前的负载均衡策略。
package com.xc.order.config;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;
/**
* @author wyp
*/
@Configuration
public class RestTemplateConfig {
@LoadBalanced
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) {
return builder.build();
}
}
3.2 修改默认负载均衡策略的方式
(1)通过配置类
需要注意的是配置类不能放在@CompentScan能扫描到的地方,否则该配置会被所有服务共享,当定义多种规则的配置类时项目启动报错。所以要创建在扫描不到的地方,用谁取谁。其实也可以不加@Configuration注解,这样放哪儿也就无所谓了。
示例:
先定义两种规则:
①负载均衡策略-随机规则
package com.xc.ribbon;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 负载均衡策略-随机规则
* @author wyp
*/
@Configuration
public class RibbonRandomRuleConfig {
/**
* 方法名必须是iRule
* @return 随机
*/
@Bean
public IRule iRule() {
return new RandomRule();
}
}
②负载均衡策略-随机+权重
package com.xc.ribbon;
import com.alibaba.cloud.nacos.ribbon.NacosRule;
import com.netflix.loadbalancer.IRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
/**
* 负载均衡策略-随机+权重
* @author wyp
*/
@Configuration
public class RibbonNacosRuleConfig {
/**
* 方法名必须是iRule
* @return nacos 随机+权重
*/
@Bean
public IRule iRule() {
return new NacosRule();
}
}
然后启动类上定义具体的服务使用的规则:
@RibbonClients(value = {
@RibbonClient(name = "A-SERVICE",configuration = RibbonNacosRuleConfig.class)
,@RibbonClient(name = "B-SERVICE",configuration = RibbonRandomRuleConfig.class)
})
意思是A-SERVICE服务下的实例采用RibbonNacosRuleConfig类下设置的规则,B-SERVICE服务下的实例采用RibbonRandomRuleConfig类下设置的规则。
(2)通过配置文件
配置语法为
服务名.ribbon.NFLoadBalancerRuleClassName=负载均衡规则的全类名
。
在application.yml中进行以下配置:
# 被调用的微服务名
A-SERVICE:
ribbon:
# 指定负载均衡策略为nacos随机+权重
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
# 被调用的微服务名
B-SERVICE:
ribbon:
# 指定负载均衡策略为随机
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule
3.3 自定义负载均衡策略
只需要继承AbstractLoadBalancerRule类,在choose方法中定义规则,然后通过以上配置类或者配置文件两种方式其中的一种进行配置即可。
示例:
public class MyLoadBalanceRule extends AbstractLoadBalancerRule {
public void initWithNiwsConfig(IClientConfig clientConfig) {
}
public Server choose(Object key) {
ILoadBalancer loadBalancer = this.getLoadBalancer();
//获取当前请求的服务实例
List<Server> reachableServers = loadBalancer.getReachableServers();
//获取具体服务(这里只获取第一台)
Server server = reachableServers.get(0);
//若服务不可用则返回null
if (!server.isAlive()){
return null;
}
return server;
}
}
3.4 开启饥饿加载
默认情况下,在第一次服务调用时才加载负载均衡器,如果网络情况不好,容易造成超时。
开启饥饿加载可在项目启动时加载负载均衡器,开启方式为在配置文件中加入如下:
ribbon:
eager-load:
# 开启ribbon饥饿加载
enabled: true
# 配置饥饿加载的服务,多个用逗号隔开
clients: A-SERVICE,B-SERVICE