0%

Ribbon简介

Ribbon:客户端负载均衡的经典实现

Ribbon 是 Netflix 开源的客户端负载均衡工具,主要用于在微服务架构中实现服务间的负载均衡调用。它通过在客户端维护服务实例列表,基于预设的负载均衡算法选择合适的服务实例,从而避免单点故障并优化资源利用率。

Ribbon 的核心定位与价值

Ribbon 是客户端负载均衡器,与 Nginx 等集中式负载均衡不同:

  • 集中式负载均衡(如 Nginx):请求先经过负载均衡器,再转发到服务实例,负载均衡逻辑独立部署;
  • 客户端负载均衡(Ribbon):负载均衡逻辑集成在客户端,客户端直接从服务注册中心获取实例列表,自主选择实例发起请求。

Ribbon 的核心价值:

  • 减少中间环节:客户端直接调用服务实例,无需经过额外负载均衡节点,降低网络延迟;
  • 灵活的负载策略:支持轮询、随机、加权等多种负载均衡算法,且允许自定义;
  • 内置容错机制:提供连接超时、重试等配置,提升服务调用的稳定性。

Ribbon 的依赖与配置

1. 引入依赖

根据 Spring Cloud 版本选择对应的 Ribbon 依赖:

  • Spring Cloud F 版及以上(推荐):

    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-ribbon</artifactId>
    </dependency>
  • 旧版本(如 Edgware 及之前):

    1
    2
    3
    4
    <dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-ribbon</artifactId>
    </dependency>

注意:若项目已引入spring-cloud-starter-openfeign,无需单独引入 Ribbon 依赖,OpenFeign 默认集成了 Ribbon。

2. 启用负载均衡

通过@LoadBalanced注解标记RestTemplate,使其具备负载均衡能力:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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;

@Configuration
public class RestTemplateConfig {

@Bean
@LoadBalanced // 关键:启用Ribbon负载均衡
public RestTemplate restTemplate() {
return new RestTemplate();
}
}
  • @LoadBalanced的底层原理是通过拦截器(LoadBalancerInterceptor)替换服务名(如MICRO-SERVICE-DEPT-PROVIDER)为具体的服务实例 IP: 端口;
  • 若未添加该注解,RestTemplate会将服务名当作域名直接请求,导致无法找到服务。

Ribbon 的服务调用方式

1. 基于服务名调用

客户端通过服务名(注册到服务中心的名称)调用服务,Ribbon 自动从服务注册中心(如 Eureka、Nacos)获取实例列表并负载均衡:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

@RestController
public class DeptConsumerController {

// 服务提供者的服务名(必须与注册中心的名称一致)
private static final String SERVICE_PROVIDER_URL = "http://MICRO-SERVICE-DEPT-PROVIDER";

@Autowired
private RestTemplate restTemplate;

@GetMapping("/consumer/dept/get/{id}")
public Dept getDept(@PathVariable("id") Long id) {
// 直接使用服务名调用,Ribbon自动负载均衡
return restTemplate.getForObject(SERVICE_PROVIDER_URL + "/dept/get/" + id, Dept.class);
}
}

注意:服务名中不能包含下划线(_),否则 Ribbon 无法正确解析,建议使用短横线(-)分隔(如MICRO-SERVICE-DEPT)。

2. 自定义负载均衡算法

Ribbon 默认使用轮询算法,若需修改,可通过配置指定:

(1)全局配置(对所有服务生效)
1
2
3
# application.yml
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule # 随机算法
(2)局部配置(仅对特定服务生效)
1
2
3
4
# 对服务名为MICRO-SERVICE-DEPT-PROVIDER的服务使用加权轮询算法
MICRO-SERVICE-DEPT-PROVIDER:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.WeightedResponseTimeRule
(3)常用内置算法
算法类名 描述
RoundRobinRule 轮询(默认)
RandomRule 随机
WeightedResponseTimeRule 加权轮询(响应时间越短的实例权重越高)
BestAvailableRule 选择并发量最小的实例(即活跃连接数最少)
RetryRule 重试机制(先按轮询选择实例,失败后重试)
(4)自定义算法(实现IRule接口)
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
30
31
32
33
34
35
36
37
38
39
40
41
42
import com.netflix.loadbalancer.ILoadBalancer;
import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.Server;
import java.util.List;
import java.util.Random;

// 自定义负载均衡算法:优先选择IP地址最后一段为偶数的实例
public class CustomRule implements IRule {
private ILoadBalancer lb;
private Random random = new Random();

@Override
public Server choose(Object key) {
List<Server> servers = lb.getReachableServers(); // 获取可用实例
if (servers.isEmpty()) return null;

// 筛选IP最后一段为偶数的实例
List<Server> filteredServers = servers.stream()
.filter(server -> {
String ip = server.getHost();
String lastSegment = ip.split("\\.")[3];
return Integer.parseInt(lastSegment) % 2 == 0;
})
.toList();

// 若没有符合条件的实例,返回随机实例
if (filteredServers.isEmpty()) {
return servers.get(random.nextInt(servers.size()));
}
return filteredServers.get(random.nextInt(filteredServers.size()));
}

@Override
public void setLoadBalancer(ILoadBalancer lb) {
this.lb = lb;
}

@Override
public ILoadBalancer getLoadBalancer() {
return lb;
}
}

配置使用自定义算法:

1
2
ribbon:
NFLoadBalancerRuleClassName: com.example.rule.CustomRule # 自定义算法类全路径

Ribbon 的核心配置参数

除负载均衡算法外,Ribbon 还支持以下关键配置:

1
2
3
4
5
6
7
# 全局配置
ribbon:
ConnectTimeout: 5000 # 连接超时时间(毫秒)
ReadTimeout: 3000 # 读取超时时间(毫秒)
MaxAutoRetries: 1 # 同一实例的最大重试次数(不包括首次调用)
MaxAutoRetriesNextServer: 1 # 切换到下一个实例的最大重试次数
OkToRetryOnAllOperations: false # 是否对所有操作重试(默认仅对GET请求重试)
  • 超时与重试:需确保ReadTimeout小于服务提供者的处理超时时间,避免提前触发重试;
  • 重试范围:默认仅对 GET 请求重试(幂等操作),POST 等非幂等请求建议关闭重试,避免重复提交。

Ribbon 的现状与替代方案

Ribbon 目前处于维护状态(Netflix 不再新增功能),Spring Cloud 官方推荐使用Spring Cloud LoadBalancer作为替代方案:

  • 与 Spring 生态更贴合,支持响应式编程;
  • 实现更轻量,无需依赖 Netflix 组件;
  • 配置方式与 Ribbon 类似,迁移成本低。

若需迁移,只需替换依赖并修改配置类:

1
2
3
4
5
<!-- 引入Spring Cloud LoadBalancer -->
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-loadbalancer</artifactId>
</dependency>

总结

Ribbon 作为客户端负载均衡的经典实现,通过简单配置即可为微服务提供负载均衡能力,是 Spring Cloud 早期生态的重要组件。其核心是通过@LoadBalanced注解增强RestTemplate,结合服务名实现动态实例选择

欢迎关注我的其它发布渠道

表情 | 预览
快来做第一个评论的人吧~
Powered By Valine
v1.3.10