hooyantsing's Blog

P21 微服务负载均衡器 Ribbon

字数统计: 1.2k阅读时长: 4 min
2022/06/21

视频源:小破站讲的最好SpringCloudAlibaba入门教程,保姆级教程通俗易懂

1. 什么是 Ribbon

目前主流的负载方案分以下两种:

  • 集中式负载均衡,在消费者和服务提供方中间使用独立的代理方式进行负载,有硬件的(比如 F5),也有软件的(比如 Nginx);
  • 客户端根据自己的请求情况做负载均衡,Ribbon 就属于客户端自己做负载均衡。

Spring Cloud Ribbon 是基于 Netflix Ribbon 实现的一套客户端的负载均衡工具,Ribbon 客户端组件提供一系列的完善配置,如超时,重试等。通过 LoadBalancer 获取到服务提供的所有机器实例,Ribbon 会自动基于某种规则(轮询、随机)去调用这些服务。Ribbon 也可以实现我们自己的负载均衡算法。

1.1 客户端的负载均衡

例如 Spring Cloud 中的 Ribbon ,客户端会有一个服务器地址列表,在发送请求前通过负载均衡算法选择一个服务器,然后进行访问,这是客户端负载均衡;即在客户端就进行负载均衡算法匹配。

image-20220621091200313

1.2 服务端的负载均衡

例如 Nginx,通过 Nginx 进行负载均衡,先发送请求,然后通过负载均衡算法,在多个服务器之间选择一个进行访问;即在服务器端再进行负载均衡算法匹配。

image-20220621091405179

1.3 常见负载均衡算法

  • 随机,通过随机选择服务进行执行,一般这种方式使用较少;
  • 轮询,负载均衡默认实现方式,请求来之后排队处理;
  • 加权轮询,通过对服务器性能的分型,给高配置、低负载的服务器分配更高的权重,均衡各个服务器的压力;
  • 地址 Hash,通过客户端请求的地址 Hash 值取模映射进行服务器调度;
  • 最小链接数,即使请求均衡了,压力不一定会均衡,最小链接数法就是根据服务器的情况,比如请求积压数等参数,将请求分配到当前压力最小的服务器。

2. Nacos 使用 Ribbon

Step 01 nacos-discovery 依赖了 ribbon,可以不用再引入 ribbon 依赖

image-20220621092231707

Step 02 添加 @LoadBalanced 注解

1
2
3
4
5
6
7
8
@Configuration
public class RestConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}

Step 03 修改 Controller

1
2
String url = "http://mall-order/order/findOrderByUserId" + id;
R result = restTemplate.getForObject(url,R.class);

3. Ribbon 内核原理

3.1 Ribbon 原理

3.2 Ribbon 负载均衡策略

image-20220621092935539

  • IRule

    这是所有负载均衡策略的父接口,里边的核心方法是 choose 方法,用来选择一个服务实例;

  • AbstractLoadBalancerRule

    AbstractLoadBalancerRule 是一个抽象类,里边主要定义了一个 ILoadBalancer,这里定义它的目的主要是辅助负责均衡策略选取合适的服务端实例。

image-20220621094258452

3.2.1 修改默认负载均衡策略
配置类方式

调用其他微服务,一律使用指定的负载均衡算法

1
2
3
4
5
6
7
8
9
@Configuration
public class RibbonRandomRuleConfig {

// 方法名一定要叫 iRule
@Bean
public IRule iRule() {
return new RandomRule();
}
}

注意,此处有坑!不能写在 @SpringBootApplication 注解的 @CompentScan 扫描得到的地方,否则自定义的配置类会被所有的 RibbonClients 共享。不建议这么使用,推荐 yml 方式。

再在 Spring Boot 启动类指定哪些服务使用该负载均衡策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
@SpringBootApplication
@RibbonClients(value = {
@RibbonClient(name = "stock-service",configuration = RibbonRandomRuleConfig.class)
})
public class OrderApplication {

public static void main(String[] args) {
SpringApplication.run(OrderApplication.class,args);
}

// 通常写在配置类里面
@Bean
@LoadBalanced
public RestTemplate restTemplate(){
RestTemplate restTemplate = new RestTemplate();
return restTemplate;
}
}
配置文件方式(推荐)

调用指定微服务提供的服务时,使用对应的负载均衡算法

修改 application.yml

1
2
3
4
5
6
7
# 服务名:
# ribbon:
# NFLoadBalancerRuleClassName: 负载均衡策略实现类全路径

stock-service:
ribbon:
NFLoadBalancerRuleClassName: com.alibaba.cloud.nacos.ribbon.NacosRule
3.2.2 自定义负载均衡策略

通过实现 IRule 接口或继承 AbstractLoadBalancerRule 抽象类可以自定义负载均衡策略,主要的选择服务逻辑在 choose 方法中。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
/**
* 自定义负载均衡策略:返回一个随机服务实例
*/
public class CustomRule extends AbstractLoadBalancerRule {
public void initWithNiwsConfig(IClientConfig iClientConfig) {

}

/**
* 负载均衡算法逻辑
*/
public Server choose(Object o) {
ILoadBalancer loadBalancer = this.getLoadBalancer();
// 获取当前请求的服务实例
List<Server> reachableServers = loadBalancer.getReachableServers();
// 获取随机数
int random = ThreadLocalRandom.current().nextInt(reachableServers.size());
return reachableServers.get(random);
}
}

3.3 饥饿加载

默认 Ribbon 处于懒加载状态,使用到时才会加载,这也就导致消费者第一次向生产者服务实例请求响应速度慢。

开启饥饿加载(禁用懒加载):

1
2
3
4
5
6
ribbon:
eager-load:
# 开启 ribbon 饥饿加载
enable: true
# 配置哪个服务使用 ribbon 饥饿加载,多个使用逗号分隔
clients: stock-service
CATALOG
  1. 1. 1. 什么是 Ribbon
    1. 1.1. 1.1 客户端的负载均衡
    2. 1.2. 1.2 服务端的负载均衡
    3. 1.3. 1.3 常见负载均衡算法
  2. 2. 2. Nacos 使用 Ribbon
  3. 3. 3. Ribbon 内核原理
    1. 3.1. 3.1 Ribbon 原理
    2. 3.2. 3.2 Ribbon 负载均衡策略
      1. 3.2.1. 3.2.1 修改默认负载均衡策略
        1. 3.2.1.1. 配置类方式
        2. 3.2.1.2. 配置文件方式(推荐)
      2. 3.2.2. 3.2.2 自定义负载均衡策略
    3. 3.3. 3.3 饥饿加载