限流器 #
一、限流概述 #
1.1 为什么需要限流 #
text
无限流:
客户端 ──► ──► ──► ──► ──► 服务
│ │
└── 大量请求 ────────────────┘
│
▼
服务过载
有限流:
客户端 ──► ──► ──► ──► ──► 限流器 ──► 服务
│ │
└── 大量请求 ────────────────┘
│
▼
超出限制被拒绝
1.2 限流算法 #
| 算法 | 说明 | 特点 |
|---|---|---|
| 令牌桶 | 按速率生成令牌 | 允许突发流量 |
| 漏桶 | 恒定速率处理 | 平滑流量 |
| 滑动窗口 | 滑动时间窗口 | 精确控制 |
二、基本使用 #
2.1 添加依赖 #
xml
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-ratelimiter</artifactId>
</dependency>
2.2 配置限流器 #
yaml
resilience4j:
ratelimiter:
configs:
default:
limitForPeriod: 10
limitRefreshPeriod: 1s
timeoutDuration: 0
instances:
userService:
baseConfig: default
orderService:
baseConfig: default
limitForPeriod: 20
2.3 使用注解 #
java
@Service
public class UserService {
@RateLimiter(name = "userService", fallbackMethod = "getUserFallback")
public User getUser(Long id) {
return userClient.getUserById(id);
}
private User getUserFallback(Long id, Throwable t) {
throw new RuntimeException("请求过于频繁,请稍后重试");
}
}
三、配置详解 #
3.1 完整配置 #
yaml
resilience4j:
ratelimiter:
configs:
default:
limitForPeriod: 10
limitRefreshPeriod: 1s
timeoutDuration: 5s
registerHealthIndicator: true
instances:
userService:
baseConfig: default
limitForPeriod: 100
orderService:
baseConfig: default
limitForPeriod: 50
3.2 配置项说明 #
| 配置项 | 默认值 | 说明 |
|---|---|---|
| limitForPeriod | 50 | 每个周期的许可数 |
| limitRefreshPeriod | 500ns | 许可刷新周期 |
| timeoutDuration | 5s | 等待许可的超时时间 |
| registerHealthIndicator | false | 是否注册健康指示器 |
3.3 计算QPS #
text
QPS = limitForPeriod / limitRefreshPeriod
例如:
limitForPeriod = 10
limitRefreshPeriod = 1s
QPS = 10 / 1 = 10
四、编程式使用 #
4.1 创建限流器 #
java
@Configuration
public class RateLimiterConfig {
@Bean
public RateLimiter userServiceRateLimiter() {
RateLimiterConfig config = RateLimiterConfig.custom()
.limitForPeriod(10)
.limitRefreshPeriod(Duration.ofSeconds(1))
.timeoutDuration(Duration.ofSeconds(5))
.build();
return RateLimiter.of("userService", config);
}
}
4.2 使用限流器 #
java
@Service
public class UserService {
@Autowired
private RateLimiter rateLimiter;
public User getUser(Long id) {
Supplier<User> supplier = RateLimiter.decorateSupplier(
rateLimiter,
() -> userClient.getUserById(id)
);
return Try.ofSupplier(supplier)
.recover(RequestNotPermitted.class, e -> {
throw new RuntimeException("请求过于频繁");
})
.get();
}
}
4.3 检查许可 #
java
@Service
public class UserService {
@Autowired
private RateLimiter rateLimiter;
public User getUser(Long id) {
if (rateLimiter.acquirePermission()) {
return userClient.getUserById(id);
} else {
throw new RuntimeException("请求过于频繁");
}
}
}
五、组合使用 #
5.1 限流+熔断 #
java
@Service
public class UserService {
@Autowired
private RateLimiter rateLimiter;
@Autowired
private CircuitBreaker circuitBreaker;
public User getUser(Long id) {
Supplier<User> supplier = SupplierUtils
.compose(
RateLimiter.decorateSupplier(rateLimiter, () -> userClient.getUserById(id)),
CircuitBreaker.decorateSupplier(circuitBreaker, () -> userClient.getUserById(id))
);
return Try.ofSupplier(supplier)
.recover(throwable -> createDefaultUser(id))
.get();
}
}
5.2 注解组合 #
java
@Service
public class UserService {
@RateLimiter(name = "userService")
@CircuitBreaker(name = "userService", fallbackMethod = "fallback")
public User getUser(Long id) {
return userClient.getUserById(id);
}
private User fallback(Long id, Throwable t) {
return createDefaultUser(id);
}
}
六、自定义限流策略 #
6.1 基于IP限流 #
java
@Configuration
public class RateLimiterConfig {
@Bean
public RateLimiter ipRateLimiter() {
return RateLimiter.of("ipRateLimiter",
RateLimiterConfig.custom()
.limitForPeriod(100)
.limitRefreshPeriod(Duration.ofSeconds(1))
.build()
);
}
}
6.2 基于用户限流 #
java
@Service
public class UserService {
private final Map<Long, RateLimiter> userRateLimiters = new ConcurrentHashMap<>();
public User getUser(Long userId, Long id) {
RateLimiter rateLimiter = userRateLimiters.computeIfAbsent(userId,
uid -> RateLimiter.of("user-" + uid,
RateLimiterConfig.custom()
.limitForPeriod(10)
.limitRefreshPeriod(Duration.ofSeconds(1))
.build()
)
);
return RateLimiter.decorateSupplier(rateLimiter,
() -> userClient.getUserById(id)
).get();
}
}
七、事件监听 #
7.1 配置事件监听 #
java
@Configuration
public class RateLimiterEventConfig {
@Bean
public RateLimiterEventListener rateLimiterEventListener(
RateLimiterRegistry registry) {
registry.getAllRateLimiters().forEach(rateLimiter -> {
rateLimiter.getEventPublisher()
.onSuccess(event -> log.info("Rate limiter success: {}", event))
.onFailure(event -> log.warn("Rate limiter failure: {}", event));
});
return new RateLimiterEventListener();
}
}
7.2 事件类型 #
| 事件类型 | 说明 |
|---|---|
| RateLimiterOnSuccessEvent | 获取许可成功 |
| RateLimiterOnFailureEvent | 获取许可失败 |
八、监控指标 #
8.1 获取指标 #
java
@RestController
public class RateLimiterController {
@Autowired
private RateLimiterRegistry registry;
@GetMapping("/rate-limiter/{name}/metrics")
public Map<String, Object> getMetrics(@PathVariable String name) {
RateLimiter rateLimiter = registry.rateLimiter(name);
RateLimiter.Metrics metrics = rateLimiter.getMetrics();
Map<String, Object> result = new HashMap<>();
result.put("availablePermissions", metrics.getAvailablePermissions());
result.put("numberOfWaitingThreads", metrics.getNumberOfWaitingThreads());
return result;
}
}
8.2 Actuator端点 #
yaml
management:
endpoints:
web:
exposure:
include: health,ratelimiters
九、最佳实践 #
9.1 生产环境配置 #
yaml
resilience4j:
ratelimiter:
configs:
default:
limitForPeriod: 100
limitRefreshPeriod: 1s
timeoutDuration: 0
registerHealthIndicator: true
instances:
userService:
baseConfig: default
limitForPeriod: 200
orderService:
baseConfig: default
limitForPeriod: 100
9.2 注意事项 #
| 注意点 | 说明 |
|---|---|
| QPS计算 | 合理计算限流阈值 |
| 超时设置 | 避免长时间等待 |
| 降级处理 | 提供友好的限流提示 |
| 监控告警 | 配置限流事件告警 |
十、总结 #
10.1 核心要点 #
| 要点 | 说明 |
|---|---|
| 令牌桶算法 | 允许突发流量 |
| 配置项 | limitForPeriod、limitRefreshPeriod |
| 注解使用 | @RateLimiter |
| 组合使用 | 与熔断器组合使用 |
10.2 下一步 #
现在你已经掌握了限流器的使用,接下来让我们学习 重试机制,了解如何实现自动重试!
最后更新:2026-03-28