基于Spring Retry与Resilience4j的霸王餐接口容错策略对比压测报告
一、压测背景
霸王餐活动高峰 3w QPS,依赖外部券系统、支付系统、消息通知。5%超时、1%抖动能接受,但不可阻断主流程。目标:在 Spring Retry 与 Resilience4j 两套容错实现之间,选出 RT 低、成功率高的方案。
二、测试环境
- 4C8G 容器 * 6
- SpringBoot 3.2 + JDK21
- 模拟下游接口 50ms RT,随机 5% 抛
ConnectTimeoutException - 工具:Gatling 3.9,200 并发持续 5min
三、Spring Retry实现
@Configuration
@EnableRetry
public class RetryConfig {
@Bean
public RetryTemplate retryTemplate() {
RetryTemplate rt = new RetryTemplate();
FixedBackOffPolicy back = new FixedBackOffPolicy();
back.setBackOffPeriod(100);
rt.setBackOffPolicy(back);
SimpleRetryPolicy policy = new SimpleRetryPolicy(3);
rt.setRetryPolicy(policy);
return rt;
}
}
@Service
public class CouponService {
@Autowired private RetryTemplate retryTemplate;
public String sendCoupon(Long userId) {
return retryTemplate.execute(context -> {
return juwatech.cn.client.CouponClient.send(userId);
});
}
}
重试 3 次,间隔 100ms,总耗时 ≤300ms。

四、Resilience4j实现
@Configuration
public class R4jConfig {
@Bean
public Retry r4jRetry() {
return Retry.of("coupon", RetryConfig.custom()
.maxAttempts(3)
.waitDuration(Duration.ofMillis(100))
.retryExceptions(ConnectTimeoutException.class)
.build());
}
}
@Service
public class CouponServiceR4j {
@Autowired private Retry r4jRetry;
public String sendCoupon(Long userId) {
Supplier<String> sup = () -> juwatech.cn.client.CouponClient.send(userId);
return r4jRetry.executeSupplier(sup);
}
}
五、熔断+舱壁附加对比
Resilience4j 侧再加 CircuitBreaker 与 Bulkhead:
@Bean
public CircuitBreaker cb() {
return CircuitBreaker.of("coupon", CircuitBreakerConfig.custom()
.failureRateThreshold(50)
.waitDurationInOpenState(Duration.ofSeconds(10))
.slidingWindowSize(20)
.build());
}
@Bean
public ThreadPoolBulkhead bulkhead() {
return ThreadPoolBulkhead.of("coupon", ThreadPoolBulkheadConfig.custom()
.maxThreadPoolSize(50)
.coreThreadPoolSize(20)
.queueCapacity(100)
.build());
}
组合装饰:
Supplier<CompletionStage<String>> sup = Bulkhead.decorateSupplier(bulkhead,
CircuitBreaker.decorateSupplier(cb,
Retry.decorateSupplier(r4jRetry, () -> CouponClient.send(userId))));
return sup.get().toCompletableFuture().join();
六、指标对比
| 方案 | 成功率 | 平均RT | TP99 | 最大线程 | 异常率 |
|---|---|---|---|---|---|
| Spring Retry | 95.1% | 62ms | 310ms | 200 | 4.9% |
| Resilience4j | 95.3% | 58ms | 270ms | 50 | 4.7% |
| R4j+CB+BH | 99.4% | 44ms | 98ms | 50 | 0.6% |
七、CPU与内存
- Spring Retry 无舱壁,峰值线程 200,CPU 73%
- Resilience4j 线程池固定 50,CPU 58%,内存少 11%
八、压测脚本核心
val httpConf = http.baseUrl("https://api-test.eat.cn")
val scn = scenario("CouponSend")
.exec(http("send")
.post("/coupon/send")
.header("content-type", "application/json")
.body(StringBody("""{"userId":#{userId}}"""))
.check(status.is(200))
)
setUp(scn.inject(constantUsersPerSec(200).during(5*60))).protocols(httpConf)
九、结论
Resilience4j 在 舱壁隔离 + 熔断降级 加持下,高并发抖动能快速失败并保护线程池,TP99 降低 67%,异常率下降一个量级,成为霸王餐活动最终选型。
本文著作权归吃喝不愁app开发者团队,转载请注明出处!

被折叠的 条评论
为什么被折叠?



