本文目录导读:

在Java中实现熔断限流,通常有三种主流方式:手动代码实现、使用开源框架(如Sentinel、Resilience4j)、以及依赖网关层(如Spring Cloud Gateway + Redis)。
以下是详细的实现方案,从简单到生产级应用。
限流实现(Rate Limiting)
限流的核心是控制访问频率,常见算法有:令牌桶、漏桶、滑动窗口。
使用 Guava RateLimiter(单机版/简单场景)
优点:代码简单,适合单机应用。 缺点:无法跨进程,不适合分布式。
import com.google.common.util.concurrent.RateLimiter;
public class RateLimiterDemo {
// 每秒生成10个令牌,即每秒最多允许10个请求
private static final RateLimiter rateLimiter = RateLimiter.create(10.0);
public static void main(String[] args) {
for (int i = 0; i < 20; i++) {
// 尝试获取令牌,若获取失败则阻塞直到获取到
double waitTime = rateLimiter.acquire();
System.out.println("请求" + i + "等待了" + waitTime + "秒");
// 业务逻辑
doBusiness();
}
}
private static void doBusiness() {
System.out.println("执行业务逻辑...");
}
}
使用 Redis + Lua 脚本(分布式限流)
原理:利用Redis的原子性操作,记录单位时间内的请求次数。
Lua 脚本(redis-rate-limiter.lua):
local key = KEYS[1] -- 限流的key
local limit = tonumber(ARGV[1]) -- 限制次数
local expire = tonumber(ARGV[2]) -- 时间窗口(秒)
local current = redis.call('INCR', key)
if current == 1 then
redis.call('EXPIRE', key, expire)
end
if current > limit then
return 0 -- 被限流
else
return 1 -- 允许通过
end
Java 调用代码:
import redis.clients.jedis.Jedis;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.script.DefaultRedisScript;
public class RedisRateLimiter {
private final RedisTemplate<String, String> redisTemplate;
private final DefaultRedisScript<Long> script;
public RedisRateLimiter(RedisTemplate<String, String> redisTemplate) {
this.redisTemplate = redisTemplate;
this.script = new DefaultRedisScript<>();
this.script.setScriptText(getScriptContent()); // 加载上面Lua脚本
this.script.setResultType(Long.class);
}
public boolean tryAcquire(String key, int limit, int expireSeconds) {
Long result = redisTemplate.execute(script,
Collections.singletonList(key),
String.valueOf(limit),
String.valueOf(expireSeconds));
return result != null && result == 1L;
}
// 使用示例:限制 userId=123 在10秒内最多只能请求5次
// tryAcquire("limiter:user:123", 5, 10)
}
熔断实现(Circuit Breaker)
熔断是为了防止级联故障(雪崩),当服务异常率过高时,快速失败(打开电路),避免长时间等待。
手动实现(状态机)
状态:关闭(允许请求) → 打开(快速失败) → 半开(尝试恢复)
public class CircuitBreaker {
private volatile CircuitState state = CircuitState.CLOSED;
private final int failureThreshold; // 触发熔断的失败次数
private final long timeout; // 熔断后到半开的时间
private int failureCount = 0;
private long lastFailureTime;
public enum CircuitState {
CLOSED, // 关闭(正常)
OPEN, // 打开(熔断)
HALF_OPEN // 半开(尝试恢复)
}
public CircuitBreaker(int failureThreshold, long timeout) {
this.failureThreshold = failureThreshold;
this.timeout = timeout;
}
public synchronized boolean allowRequest() {
switch (state) {
case CLOSED:
return true;
case OPEN:
// 检查是否过了熔断时间,是则转为半开
if (System.currentTimeMillis() - lastFailureTime > timeout) {
state = CircuitState.HALF_OPEN;
return true;
}
return false;
case HALF_OPEN:
return true;
}
return false;
}
public synchronized void recordSuccess() {
if (state == CircuitState.HALF_OPEN) {
state = CircuitState.CLOSED;
failureCount = 0;
}
}
public synchronized void recordFailure() {
failureCount++;
lastFailureTime = System.currentTimeMillis();
if (failureCount >= failureThreshold) {
state = CircuitState.OPEN;
}
}
}
使用方式:
public class BusinessService {
private CircuitBreaker breaker = new CircuitBreaker(5, 10_000); // 5次失败,熔断10秒
public String call() {
if (!breaker.allowRequest()) {
throw new RuntimeException("Circuit breaker is open, request rejected");
}
try {
// 调用下游服务
String result = callDownstream();
breaker.recordSuccess();
return result;
} catch (Exception e) {
breaker.recordFailure();
throw e;
}
}
}
主流生产框架推荐
Sentinel(阿里开源的流量防卫兵)
特点:
- 支持实时监控
- 支持熔断降级、系统自适应保护
- 支持注解,配置灵活
引入依赖:
<dependency>
<groupId>com.alibaba.csp</groupId>
<artifactId>sentinel-core</artifactId>
<version>1.8.6</version>
</dependency>
使用注解实现限流熔断:
@Service
public class OrderService {
// 限流:每秒最多允许20个请求
@SentinelResource(value = "createOrder",
blockHandler = "blockHandlerMethod",
fallback = "fallbackMethod")
public String createOrder(String userId) {
// 正常业务逻辑
return "Order created for " + userId;
}
// 限流后的处理
public String blockHandlerMethod(String userId, BlockException e) {
return "Too many requests, please try later.";
}
// 服务异常后的降级
public String fallbackMethod(String userId, Throwable e) {
return "Service unavailable, fallback.";
}
}
Resilience4j(Spring Cloud Circuit Breaker 默认实现)
特点:
- 轻量级,与Hystrix类似但更现代
- 功能模块化:熔断、重试、限流、隔离
引入依赖:
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-spring-boot2</artifactId>
<version>2.0.2</version>
</dependency>
yaml 配置:
resilience4j:
circuitbreaker:
instances:
userService:
registerHealthIndicator: true
slidingWindowSize: 10 # 滑动窗口大小
minimumNumberOfCalls: 5 # 最少请求次数
failureRateThreshold: 50 # 失败率阈值(百分比)
waitDurationInOpenState: 10s # 熔断保持时间
ratelimiter:
instances:
userService:
limitForPeriod: 10 # 周期内最大请求数
limitRefreshPeriod: 1s # 刷新周期
Java 使用:
@RestController
public class UserController {
@GetMapping("/user/{id}")
@CircuitBreaker(name = "userService", fallbackMethod = "userFallback")
@RateLimiter(name = "userService")
public String getUser(@PathVariable String id) {
// 调用下游服务
return restTemplate.getForObject("http://user-service/user/" + id, String.class);
}
public String userFallback(Exception e) {
return "Fallback: Service is unavailable.";
}
}
网关层限流(常用方案)
Spring Cloud Gateway + RequestRateLimiter
原理:基于Redis的令牌桶算法。
配置:
spring:
cloud:
gateway:
routes:
- id: user-service-route
uri: lb://user-service
predicates:
- Path=/api/user/**
filters:
- name: RequestRateLimiter
args:
key-resolver: "#{@userKeyResolver}" # 限流key提取器
redis-rate-limiter.replenishRate: 10 # 令牌每秒填充数
redis-rate-limiter.burstCapacity: 20 # 最大令牌数
# 自定义 key-resolver
@Bean
public KeyResolver userKeyResolver() {
return exchange -> Mono.just(
exchange.getRequest().getRemoteAddress().getAddress().getHostAddress()
);
}
总结与最佳实践
| 场景 | 推荐方案 | 说明 |
|---|---|---|
| 单机限流 | Guava RateLimiter | 简单,但无法分布式 |
| 分布式限流 | Redis + Lua | 性能好,适合多实例部署 |
| 熔断降级 | Resilience4j / Sentinel | 生产级,支持监控 |
| 网关限流 | Spring Cloud Gateway + Redis | 统一入口控制 |
| 复杂策略 | Sentinel | 支持热点限流、系统保护、集群流控 |
关键原则:
- 限流和熔断要配合使用:限流防止过载,熔断防止级联故障。
- 合理设置阈值:基于压测数据调整,避免误杀或失效。
- 降级处理:熔断时提供默认的 fallback 返回,避免前端白屏。
- 监控和告警:结合 Prometheus + Grafana 监控熔断/限流状态。