Ribbon负载均衡
2026/1/15大约 4 分钟EurekaRibbon负载均衡
Ribbon 负载均衡
一、Ribbon 简介
Ribbon 是 Netflix 开源的客户端负载均衡器,与 Eureka 配合使用,可以实现服务调用的负载均衡。
1.1 服务端负载均衡 vs 客户端负载均衡
| 类型 | 代表 | 特点 |
|---|---|---|
| 服务端负载均衡 | Nginx、F5 | 集中式,需要额外部署 |
| 客户端负载均衡 | Ribbon | 分布式,集成在客户端 |
二、Ribbon 工作原理
2.1 工作流程
2.2 核心组件
| 组件 | 说明 |
|---|---|
| ILoadBalancer | 负载均衡器接口 |
| IRule | 负载均衡策略 |
| IPing | 服务健康检查 |
| ServerList | 服务列表 |
| ServerListFilter | 服务列表过滤器 |
三、负载均衡策略
3.1 内置策略
| 策略 | 类名 | 说明 |
|---|---|---|
| 轮询 | RoundRobinRule | 默认策略,依次轮询 |
| 随机 | RandomRule | 随机选择 |
| 重试 | RetryRule | 轮询失败后重试 |
| 权重 | WeightedResponseTimeRule | 根据响应时间分配权重 |
| 最少连接 | BestAvailableRule | 选择并发最少的实例 |
| 可用过滤 | AvailabilityFilteringRule | 过滤故障和高并发实例 |
| 区域感知 | ZoneAvoidanceRule | 综合区域和可用性 |
3.2 策略详解
轮询策略(RoundRobinRule)
// 伪代码
public Server choose(List<Server> servers) {
int index = counter.incrementAndGet() % servers.size();
return servers.get(index);
}随机策略(RandomRule)
public Server choose(List<Server> servers) {
int index = random.nextInt(servers.size());
return servers.get(index);
}权重策略(WeightedResponseTimeRule)
四、配置负载均衡策略
4.1 全局配置
@Configuration
public class RibbonConfig {
@Bean
public IRule ribbonRule() {
// 使用随机策略
return new RandomRule();
}
}4.2 针对特定服务配置
# 针对 user-service 使用随机策略
user-service:
ribbon:
NFLoadBalancerRuleClassName: com.netflix.loadbalancer.RandomRule4.3 配置类方式
// 不要放在 @ComponentScan 扫描范围内
@Configuration
public class UserServiceRibbonConfig {
@Bean
public IRule ribbonRule() {
return new RandomRule();
}
}
// 主配置类
@SpringBootApplication
@RibbonClient(name = "user-service", configuration = UserServiceRibbonConfig.class)
public class OrderServiceApplication {
// ...
}五、自定义负载均衡策略
5.1 实现 IRule 接口
public class CustomRule extends AbstractLoadBalancerRule {
@Override
public Server choose(Object key) {
ILoadBalancer lb = getLoadBalancer();
List<Server> servers = lb.getReachableServers();
if (servers.isEmpty()) {
return null;
}
// 自定义选择逻辑:选择端口最小的实例
return servers.stream()
.min(Comparator.comparingInt(Server::getPort))
.orElse(null);
}
@Override
public void initWithNiwsConfig(IClientConfig config) {
// 初始化配置
}
}5.2 基于权重的自定义策略
public class WeightRule extends AbstractLoadBalancerRule {
@Override
public Server choose(Object key) {
List<Server> servers = getLoadBalancer().getReachableServers();
// 获取权重总和
int totalWeight = servers.stream()
.mapToInt(this::getWeight)
.sum();
// 随机选择
int random = ThreadLocalRandom.current().nextInt(totalWeight);
int current = 0;
for (Server server : servers) {
current += getWeight(server);
if (random < current) {
return server;
}
}
return servers.get(0);
}
private int getWeight(Server server) {
// 从元数据获取权重
Map<String, String> metadata = ((DiscoveryEnabledServer) server)
.getInstanceInfo().getMetadata();
String weight = metadata.getOrDefault("weight", "1");
return Integer.parseInt(weight);
}
}六、Ribbon 配置参数
6.1 常用配置
ribbon:
# 连接超时(毫秒)
ConnectTimeout: 2000
# 读取超时(毫秒)
ReadTimeout: 5000
# 同一实例最大重试次数
MaxAutoRetries: 1
# 其他实例最大重试次数
MaxAutoRetriesNextServer: 2
# 是否所有操作都重试
OkToRetryOnAllOperations: false
# 服务列表刷新间隔
ServerListRefreshInterval: 300006.2 针对特定服务配置
user-service:
ribbon:
ConnectTimeout: 3000
ReadTimeout: 10000
MaxAutoRetries: 2
MaxAutoRetriesNextServer: 3七、饥饿加载
7.1 问题
Ribbon 默认懒加载,第一次调用时才创建客户端,导致首次调用较慢。
7.2 配置饥饿加载
ribbon:
eager-load:
enabled: true
clients: user-service,order-service八、Ribbon 与 RestTemplate
8.1 配置 LoadBalanced
@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate() {
return new RestTemplate();
}
}8.2 使用服务名调用
@Service
public class OrderService {
@Autowired
private RestTemplate restTemplate;
public User getUser(Long id) {
// 使用服务名,Ribbon 自动负载均衡
String url = "http://user-service/user/" + id;
return restTemplate.getForObject(url, User.class);
}
}九、总结
核心要点:
- 客户端负载均衡:在消费者端实现
- 多种策略:轮询、随机、权重等
- 可扩展:支持自定义策略
- 与 Eureka 集成:自动获取服务列表
