SpringBoot中的重试、限流、熔断与幂等的“四重奏”
一、先翻车,再修车:为什么需要这“四大金刚”?🤔
// 翻车现场示例
@Service
public class CrashService {
public String callExternalApi() {
// 这个外部API:时好时坏,慢如蜗牛,偶尔还宕机
return restTemplate.getForObject("http://不靠谱的第三方/api", String.class);
}
}
// 问题清单:
// 1. 网络闪断一次就失败 → 需要重试
// 2. 瞬间涌入10000个请求 → 需要限流
// 3. 对方服务彻底挂了还一直调用 → 需要熔断
// 4. 重试导致同一订单创建了5次 → 需要幂等2
3
4
5
6
7
8
9
10
11
12
13
二、重试机制:给失败者再来一次的机会 ♻️
Spring Retry + Resilience4j 双剑合璧
@Configuration
@EnableRetry // 开启Spring重试魔法
public class RetryConfig {
// 方法级别重试:像追女朋友,不能太频繁,但要坚持几次
@Bean
public RetryTemplate retryTemplate() {
return RetryTemplate.builder()
.maxAttempts(3) // 最多表白3次
.fixedBackoff(1000) // 每次失败后冷静1秒
.retryOn(ResourceAccessException.class) // 只在网络异常时重试
.traversingCauses() // 连异常的原因一起检查
.build();
}
}
@Service
public class OrderService {
// 注解式重试:只需一个注解,轻松拥有“牛皮糖”特性
@Retryable(
value = {TimeoutException.class, SocketException.class}, // 这些异常才重试
maxAttempts = 3, // 最多3次
backoff = @Backoff(delay = 1000, multiplier = 2) // 延迟1秒,下次翻倍
)
public String placeOrder(Order order) {
// 调用支付接口
return paymentClient.pay(order);
}
// 重试都失败后的“兜底方案”:比如发个通知或记录日志
@Recover
public String recover(TimeoutException e, Order order) {
log.error("支付服务呼叫失败,订单转入人工处理: {}", order.getId());
return "pending"; // 返回挂起状态
}
}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
三、限流:拒绝“双十一”式挤兑 🚦
@Configuration
public class RateLimitConfig {
@Bean
public RateLimiterRegistry rateLimiterRegistry() {
return RateLimiterRegistry.of(
RateLimiterConfig.custom()
.limitForPeriod(100) // 1秒内最多100个请求
.limitRefreshPeriod(Duration.ofSeconds(1)) // 时间窗口1秒
.timeoutDuration(Duration.ofMillis(500)) // 等待超时500ms
.build()
);
}
// 更简单的方案:Guava RateLimiter
@Bean
public RateLimiter guavaRateLimiter() {
return RateLimiter.create(50.0); // 每秒50个令牌
}
}
@RestController
@RequestMapping("/api/products")
public class ProductController {
private final RateLimiter rateLimiter;
// 在热门商品接口上加个“保安”
@GetMapping("/hot/{id}")
public Product getHotProduct(@PathVariable String id) {
// 拿不到令牌就快速失败,避免排队堵死系统
if (!rateLimiter.acquire(1, 50, TimeUnit.MILLISECONDS)) {
throw new TooManyRequestsException("客官稍等,服务器在喘气...");
}
return productService.getProduct(id);
}
// 使用@Aspect统一限流(更优雅)
@RateLimiterAspect(name = "productApi", limit = 100)
@GetMapping("/{id}")
public Product getProduct(@PathVariable String id) {
// 业务逻辑...
}
}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
43
44
四、熔断器:该放弃时就放弃,及时止损 ⚡
@Configuration
public class CircuitBreakerConfig {
@Bean
public CircuitBreakerRegistry circuitBreakerRegistry() {
return CircuitBreakerRegistry.of(
CircuitBreakerConfig.custom()
.slidingWindowSize(10) // 统计最近10次调用
.failureRateThreshold(50) // 失败率超50%就熔断
.waitDurationInOpenState(Duration.ofSeconds(10)) // 熔断后10秒进入半开
.permittedNumberOfCallsInHalfOpenState(5) // 半开状态允许5次试探
.build()
);
}
}
@Component
@Slf4j
public class PaymentService {
private final CircuitBreaker circuitBreaker;
// 给第三方支付加个“保险丝”
public PaymentResult pay(Order order) {
return circuitBreaker.executeSupplier(() -> {
// 尝试调用支付网关
PaymentGatewayResponse response = paymentGateway.process(order);
if (!response.isSuccess()) {
// 业务失败也要算作失败次数
throw new PaymentException("支付失败: " + response.getError());
}
return response.toPaymentResult();
}, throwable -> {
// 熔断时的降级方案:记录订单,稍后人工处理
log.warn("支付服务熔断,订单{}进入待处理队列", order.getId());
return PaymentResult.pending(order.getId());
});
}
}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
五、幂等性:同个操作做一次和做一百次效果一样 ✅
@Service
@Slf4j
public class IdempotentService {
// 方案1:数据库唯一索引(最简单粗暴)
public void createOrderWithUniqueId(Order order) {
try {
// order_no字段有唯一索引
orderRepository.save(order);
} catch (DataIntegrityViolationException e) {
// 重复插入会抛出异常,直接返回已存在的订单
log.info("订单已存在: {}", order.getOrderNo());
return orderRepository.findByOrderNo(order.getOrderNo());
}
}
// 方案2:Token机制(前端配合)
public ApiResponse<String> getToken(String userId) {
String token = UUID.randomUUID().toString();
// 存入Redis,5分钟过期
redisTemplate.opsForValue().set(
"idempotent:token:" + userId,
token,
5, TimeUnit.MINUTES
);
return ApiResponse.success(token);
}
@PostMapping("/orders")
public ApiResponse<Order> createOrder(
@RequestBody OrderRequest request,
@RequestHeader("X-Idempotent-Token") String token) {
String redisKey = "idempotent:order:" + token;
// 用setIfAbsent实现原子性检查
Boolean isNew = redisTemplate.opsForValue()
.setIfAbsent(redisKey, "processing", 24, TimeUnit.HOURS);
if (Boolean.FALSE.equals(isNew)) {
// token已使用,返回之前的处理结果
String cachedResult = redisTemplate.opsForValue().get(redisKey);
if ("processing".equals(cachedResult)) {
return ApiResponse.error("请求处理中,请勿重复提交");
}
return ApiResponse.success(cachedResult);
}
try {
// 真正的业务处理
Order order = orderService.createOrder(request);
// 处理完成,缓存结果
redisTemplate.opsForValue().set(redisKey, order.getId(), 24, TimeUnit.HOURS);
return ApiResponse.success(order);
} catch (Exception e) {
// 出错删除token,允许重试
redisTemplate.delete(redisKey);
throw e;
}
}
// 方案3:分布式锁 + 状态机
public void updateOrderStatus(String orderId, OrderStatus newStatus) {
String lockKey = "order:update:" + orderId;
RLock lock = redissonClient.getLock(lockKey);
try {
if (lock.tryLock(3, 10, TimeUnit.SECONDS)) {
Order order = orderRepository.findById(orderId)
.orElseThrow(() -> new OrderNotFoundException(orderId));
// 检查状态流转是否合法
if (!order.getStatus().canTransferTo(newStatus)) {
throw new IllegalStatusException("状态流转非法");
}
order.setStatus(newStatus);
orderRepository.save(order);
}
} finally {
if (lock.isHeldByCurrentThread()) {
lock.unlock();
}
}
}
}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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
六、四合一豪华套餐:整合实战 🍱
@RestController
@Slf4j
public class SuperResilientController {
// 完整的韧性配置
@PostMapping("/v1/orders")
@Idempotent(tokenHeader = "X-Request-Id") // 自定义幂等注解
@RateLimiter(name = "createOrder", limit = 50) // 限流
@CircuitBreaker(name = "paymentService", fallbackMethod = "createOrderFallback") // 熔断
@Retryable(value = TimeoutException.class, maxAttempts = 2) // 重试
public ApiResponse<Order> createOrder(@Valid @RequestBody OrderRequest request) {
// 1. 参数校验(JSR-303)
// 2. 生成幂等ID(如果header没有)
String idempotentId = generateIdempotentId(request);
// 3. 调用库存服务(自动享受重试+熔断)
inventoryService.deductStock(request.getItems());
// 4. 创建订单(幂等保证)
Order order = orderService.createIdempotentOrder(request, idempotentId);
// 5. 调用支付(最可能出问题的环节)
PaymentResult result = paymentService.pay(order);
// 6. 更新订单状态
orderService.updateOrderStatus(order.getId(), OrderStatus.PAID);
return ApiResponse.success(order);
}
// 熔断降级方法:创建本地订单,标记为待支付
private ApiResponse<Order> createOrderFallback(OrderRequest request, Exception e) {
log.warn("订单创建熔断,降级处理", e);
// 保存到待处理表,后续定时任务重试
PendingOrder pendingOrder = new PendingOrder();
pendingOrder.setRequestData(JsonUtils.toJson(request));
pendingOrder.setStatus("pending");
pendingOrderRepository.save(pendingOrder);
return ApiResponse.success(
Order.builder()
.id("pending-" + System.currentTimeMillis())
.status(OrderStatus.PENDING)
.message("系统繁忙,订单已记录,稍后为您处理")
.build()
);
}
// 统一异常处理
@ExceptionHandler
public ApiResponse<?> handleException(Exception e) {
if (e instanceof TooManyRequestsException) {
return ApiResponse.error(429, "请求太多,歇会儿再来");
}
if (e instanceof CircuitBreakerOpenException) {
return ApiResponse.error(503, "服务暂时不可用,请稍后重试");
}
// ... 其他异常处理
return ApiResponse.error(500, "服务器开小差了");
}
}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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
七、监控与调优:没有监控的韧性就是耍流氓 📊
# application.yml - 完整的韧性配置
resilience4j:
circuitbreaker:
instances:
paymentService:
failure-rate-threshold: 50
wait-duration-in-open-state: 10s
sliding-window-size: 20
ratelimiter:
instances:
orderApi:
limit-for-period: 100
limit-refresh-period: 1s
retry:
instances:
externalApi:
max-attempts: 3
wait-duration: 1s
# Micrometer指标暴露
management:
endpoints:
web:
exposure:
include: health,info,metrics,circuitbreakers,ratelimiters
metrics:
export:
prometheus:
enabled: true2
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
// 可视化熔断器状态
@Component
@Slf4j
public class CircuitBreakerMonitor {
@EventListener
public void onStateChange(CircuitBreakerOnStateTransitionEvent event) {
log.info("熔断器 {} 状态变化: {} -> {}, 失败率: {}%",
event.getCircuitBreakerName(),
event.getStateTransition().getFromState(),
event.getStateTransition().getToState(),
event.getCircuitBreaker().getMetrics().getFailureRate());
}
// 发送告警到钉钉/企业微信
public void sendAlert(CircuitBreaker circuitBreaker) {
if (circuitBreaker.getState() == CircuitBreaker.State.OPEN) {
alertService.send("【系统告警】服务" + circuitBreaker.getName() + "已熔断!");
}
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
八、实战小贴士 💡
重试:不是所有异常都要重试!数据库主键冲突、参数错误等重试也没用
限流:入口处就要限,别等流量把数据库冲垮了再限
熔断:半开状态要小心,少量流量试探,成功再逐步恢复
幂等:GET请求天然幂等,重点保护POST/PUT/DELETE
组合策略:
- 先限流,保护系统不被冲垮
- 再熔断,快速失败避免雪崩
- 配合重试,给临时故障机会
- 幂等兜底,防止重复操作
九、总结:韧性设计的“四不”原则 🎯
- 打不死:重试机制给临时故障“再来一次”的机会
- 挤不垮:限流让系统在流量洪峰前“礼貌拒绝”
- 不陪葬:熔断在依赖服务宕机时“及时止损”
- 不重复:幂等性让重复请求“只生效一次”
记住,没有银弹!这些策略需要根据业务特点调整参数。监控是关键,没有监控的韧性配置就像闭着眼睛开车——翻车是迟早的事。
最后送大家一句: 在分布式系统的世界里,唯一不变的就是故障总会发生。我们要做的不是追求100%可用,而是故障发生时,系统能优雅地“摔倒”,然后帅气地“站起来”!💪
各位 骑手们,是否曾在深夜被警报惊醒,发现某个服务接口突然“躺平”?或是流量洪峰时系统直接“摆烂”?今天咱们就来聊聊 Java 领域的容错界超级英雄——Resilience4j!
🤔 为什么需要容错框架?
想象一下:你去餐馆吃饭(调用服务),结果后厨着火(服务宕机)、厨师吵架(服务异常)、上菜慢如蜗牛(服务超时)… 作为食客,你肯定希望:
- 后厨着火时,经理立刻挂出“暂停营业”(熔断)
- 厨师吵架时,领班让备用厨师顶上(降级/重试)
- 人多时让顾客分批进入(限流)
Resilience4j 就是帮你实现这些策略的“餐厅智能管理系统”!
🧩 Resilience4j 核心设计:轻量而强大
与 Netflix Hystrix 相比,Resilience4j 有三大优势:
- 📦 轻量级:基于 Vavr 函数式库,无外部依赖
- 🎯 模块化:可按需引入熔断、限流、重试等模块
- ⚡ 函数式友好:完美支持 Lambda 和函数式接口
Resilience4j 核心模块结构图
Resilience4j是一个轻量级的容错库,提供了多种核心模块来提升系统的弹性和稳定性。
核心模块
| 模块名称 | 功能描述 |
|---|---|
| Circuit Breaker (断路器) | 在远程服务故障时快速失败,防止故障扩散 |
| Rate Limiter (限流器) | 控制请求速率,避免系统过载 |
| Retry (重试) | 在操作失败时自动重试,提高可用性 |
| Bulkhead (舱壁隔离) | 限制并发执行数量,保护系统资源 |
| Time Limiter (超时控制) | 设置操作超时时间,避免长时间阻塞 |
| Cache (缓存) | 缓存操作结果,减少重复计算或调用 |
这些模块可以单独使用,也可以组合使用,以构建更具弹性的系统架构。
<!-- Resilience4j 容错库核心模块依赖集合,用于提升系统弹性 -->
<dependencies>
<!-- 断路器模块:在远程服务故障时快速失败,防止故障扩散 -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-circuitbreaker</artifactId>
<version>2.0.2</version>
</dependency>
<!-- 限流器模块:控制请求速率,避免系统过载 -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-ratelimiter</artifactId>
<version>2.0.2</version>
</dependency>
<!-- 重试模块:在操作失败时自动重试,提高可用性 -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-retry</artifactId>
<version>2.0.2</version>
</dependency>
<!-- 舱壁隔离模块:限制并发执行数量,保护系统资源 -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-bulkhead</artifactId>
<version>2.0.2</version>
</dependency>
<!-- 超时控制模块:设置操作超时时间,避免长时间阻塞 -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-timelimiter</artifactId>
<version>2.0.2</version>
</dependency>
<!-- 缓存模块:缓存操作结果,减少重复计算或调用 -->
<dependency>
<groupId>io.github.resilience4j</groupId>
<artifactId>resilience4j-cache</artifactId>
<version>2.0.2</version>
</dependency>
</dependencies>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
43
44
🔥 明星功能一:熔断器(Circuit Breaker)
熔断器就像家里的电闸,短路时自动跳闸,防止火灾蔓延!
工作原理(三状态机):
- 🟢 CLOSED(闭合) :正常通行,但会记录失败率
- 🟡 HALF_OPEN(半开) :尝试放行少量请求,探测服务是否恢复
- 🔴 OPEN(断开) :直接拒绝请求,走降级逻辑
// 🎪 熔断器实战示例
CircuitBreakerConfig config = CircuitBreakerConfig.custom()
.failureRateThreshold(50) // 失败率阈值 50%
.waitDurationInOpenState(Duration.ofSeconds(10)) // 10秒后进入半开
.slidingWindowSize(5) // 基于最近5次调用计算失败率
.build();
CircuitBreaker circuitBreaker = CircuitBreaker.of("userService", config);
// 🎯 使用熔断器保护服务调用
Supplier<String> decoratedSupplier = CircuitBreaker
.decorateSupplier(circuitBreaker, this::callUserService);
try {
return Try.ofSupplier(decoratedSupplier)
.recover(throwable -> "降级:默认用户数据"); // 优雅降级!
} catch (Exception e) {
return "熔断开启,服务暂时不可用";
}
private String callUserService() {
// 这里是你真正的服务调用逻辑
if (Math.random() > 0.7) {
throw new RuntimeException("服务不稳定!");
}
return "用户数据获取成功";
}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
🚦 明星功能二:限流器(Rate Limiter)
限流器就像游乐园的排队栏杆,防止人潮挤爆设施!
// 🎪 限流器配置:每秒最多 10 个请求
RateLimiterConfig limiterConfig = RateLimiterConfig.custom()
.limitForPeriod(10)
.limitRefreshPeriod(Duration.ofSeconds(1))
.timeoutDuration(Duration.ofMillis(500)) // 最多等待 500ms
.build();
RateLimiter rateLimiter = RateLimiter.of("apiLimiter", limiterConfig);
// 🎯 装饰你的方法
CheckedFunction0<String> restrictedFunction = RateLimiter
.decorateCheckedSupplier(rateLimiter, this::expensiveApiCall);
Try<String> result = Try.of(restrictedFunction)
.onSuccess(res -> log.info("API 调用成功: {}", res))
.onFailure(ex -> log.warn("请求被限流或超时", ex));2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
🔁 明星功能三:重试(Retry)
重试机制就像追对象,一次失败?等等再试几次!但要有限度~
// 🎪 重试配置:最多重试3次,间隔递增
RetryConfig retryConfig = RetryConfig.custom()
.maxAttempts(3) // 最多尝试3次(包含第一次)
.waitDuration(Duration.ofMillis(100)) // 初始等待100ms
.intervalFunction(IntervalFunction.ofExponentialBackoff()) // 指数退避
.retryOnResult(response -> response.contains("临时失败")) // 根据结果重试
.retryExceptions(IOException.class, TimeoutException.class) // 根据异常重试
.build();
Retry retry = Retry.of("uploadRetry", retryConfig);
// 🎯 使用重试装饰上传功能
Supplier<String> retryableUpload = Retry
.decorateSupplier(retry, this::uploadFile);
String uploadResult = retryableUpload.get(); // 会自动重试哦!2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
🧩 模块组合:打造无敌防御体系
真正的强大在于组合技能!
// 🎪 组合使用:熔断 + 重试 + 限流(超级防御!)
CircuitBreaker circuitBreaker = CircuitBreaker.ofDefaults("userService");
Retry retry = Retry.ofDefaults("userService");
RateLimiter rateLimiter = RateLimiter.ofDefaults("userService");
// 🎯 装饰顺序很重要:重试 -> 熔断 -> 限流
Supplier<String> decoratedSupplier = Supplier.of(this::callUserService)
.decorate(Retry.decorateSupplier(retry)) // 先重试
.decorate(CircuitBreaker.decorateSupplier(circuitBreaker)) // 再熔断
.decorate(RateLimiter.decorateSupplier(rateLimiter)); // 最后限流
// 🎪 更优雅的写法:使用装饰器链
Supplier<String> chainedSupplier = Decorators.ofSupplier(this::callUserService)
.withRetry(retry)
.withCircuitBreaker(circuitBreaker)
.withRateLimiter(rateLimiter)
.decorate();
return Try.ofSupplier(chainedSupplier)
.recover(throwable -> "所有防御都失败了,返回兜底数据");2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
🚀 集成:一键起飞
如果你用 Spring Boot,集成简单到哭!
# 🎪 application.yml 配置
resilience4j:
circuitbreaker:
instances:
userService:
failure-rate-threshold: 50
sliding-window-size: 10
retry:
instances:
userService:
max-attempts: 3
wait-duration: 100ms2
3
4
5
6
7
8
9
10
11
12
// 🎪 在 Spring Boot 中使用注解(真香!)
@Service
public class UserService {
@CircuitBreaker(name = "userService", fallbackMethod = "fallback")
@Retry(name = "userService", fallbackMethod = "fallback")
@RateLimiter(name = "userService", fallbackMethod = "fallback")
@TimeLimiter(name = "userService", fallbackMethod = "fallbackAsync")
public CompletableFuture<String> getUserById(String userId) {
// 你的业务逻辑
return CompletableFuture.completedFuture("用户数据");
}
// 🎯 同步降级方法
private String fallback(String userId, Exception e) {
return "降级:默认用户数据";
}
// 🎯 异步降级方法(用于 TimeLimiter)
private CompletableFuture<String> fallbackAsync(String userId, Exception e) {
return CompletableFuture.completedFuture("异步降级数据");
}
}2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
📊 监控与指标:知己知彼
Resilience4j 还提供丰富的监控指标:
// 🎪 获取熔断器状态
CircuitBreaker.Metrics metrics = circuitBreaker.getMetrics();
float failureRate = metrics.getFailureRate(); // 当前失败率
int bufferedCalls = metrics.getNumberOfSuccessfulCalls(); // 成功调用数
// 🎪 事件监听(用于日志或报警)
circuitBreaker.getEventPublisher()
.onSuccess(event -> log.info("调用成功: {}", event))
.onError(event -> log.error("调用失败", event.getThrowable()))
.onStateTransition(event -> log.warn("状态变更: {} -> {}",
event.getStateTransition().getFromState(),
event.getStateTransition().getToState()));
// 🎪 与 Micrometer 集成(Prometheus + Grafana 展示)
CircuitBreakerRegistry circuitBreakerRegistry = CircuitBreakerRegistry.ofDefaults();
TaggedCircuitBreakerMetrics.ofCircuitBreakerRegistry(circuitBreakerRegistry)
.bindTo(Metrics.globalRegistry);2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
🎯 最佳实践与小贴士
- 🔧 因地制宜:不同服务配置不同参数,核心服务用严格配置
- 👀 监控告警:一定要监控熔断器状态变化,及时介入
- 🧪 测试覆盖:用 Chaos Monkey 等工具模拟故障,测试容错效果
- 📈 渐进调整:根据实际数据逐步调整阈值和超时时间
// 🎪 动态配置示例:根据业务压力调整限流
private void adjustRateLimitByTime() {
int hour = LocalTime.now().getHour();
int limit = (hour >= 9 && hour <= 18) ? 100 : 20; // 工作时间 100QPS,其他时间 20QPS
RateLimiterConfig newConfig = RateLimiterConfig.custom()
.limitForPeriod(limit)
.limitRefreshPeriod(Duration.ofSeconds(1))
.build();
// 动态更新配置(部分实现支持热更新)
rateLimiter.changeLimitForPeriod(limit);
}2
3
4
5
6
7
8
9
10
11
12
13
🎁 总结
Resilience4j 就像给你的微服务穿上多层防护甲:
- 熔断器是主防护,防止雪崩
- 限流器是流量警察,维护秩序
- 重试机制是乐观主义者,相信下次能成功
- 隔离舱是空间规划师,避免资源争抢
马年新气象,祝各位的 Java 服务都能一马当先、马到成功,永不“马”失前蹄! 🐴💨
记住:没有银弹,只有合适的锤子敲合适的钉子!
彩蛋:你知道为什么叫 Resilience4j 吗?因为开发者希望你的系统能像弹簧(resilience)一样,被压垮后还能弹回来!💪
