本文目录导读:

重试策略的配置通常取决于你使用的具体工具、框架或云服务(如 HTTP 客户端、消息队列、数据库连接池、云 SDK 等),不同的场景下,配置方式差异很大。
为了给你最准确的信息,我将最常见的几种场景分类说明,你可以根据你的技术栈对号入座。
核心原则(无论哪种工具都要考虑)
在配置重试策略前,建议先明确以下三个参数:
- 最大重试次数 (Max Retries):允许重试的总次数,防止无限重试耗尽资源。
- 重试间隔策略 (Backoff Strategy):
- 固定间隔:每次等待相同时间(如 2 秒),容易造成“惊群效应”。
- 增量间隔:每次递增等待时间(如 2s, 4s, 6s)。
- 指数退避:每次翻倍(如 1s, 2s, 4s, 8s),最常用且对系统最友好。
- 随机抖动:在间隔基础上加一个随机值,强烈推荐用于避免多个请求同时重试导致服务雪崩。
- 重试条件 (Retryable Conditions):不要对所有错误都重试。
- 应该重试:网络超时(Timeout)、服务端错误(5xx,尤其是 500/503/502)、连接被拒绝 (Connection Refused)。
- 不应该重试:客户端错误(4xx,尤其是 400 坏请求、401 未授权、403 禁止、404 不存在)、资源冲突(409 重复提交)或你想手动终止的请求。
常见工具/框架的配置方法
HTTP 客户端(最常用)
Python(使用 requests 或 urllib3)
# 使用 retry 库(需安装:pip install retry)
from retry import retry
import requests
@retry(exceptions=requests.exceptions.RequestException, tries=3, delay=2, backoff=2, jitter=(1, 3))
def fetch_data(url):
response = requests.get(url, timeout=5)
response.raise_for_status() # 触发重试
return response.json()
# 参数:tries=3 次尝试,delay=2 秒初始等待,backoff=2 指数因子,jitter 加入随机抖动
# 或使用 urllib3 的 Retry 类
from urllib3.util.retry import Retry
retry_strategy = Retry(
total=3, # 总重试次数
backoff_factor=0.5, # 间隔基数(公式:{backoff factor} * (2 ** ({number of retries} - 1)))
status_forcelist=[500, 502, 503, 504], # 只对服务端错误重试
allowed_methods=["GET", "POST"] # 只对幂等方法重试
)
# 然后配置到 requests.Session 中
from requests.adapters import HTTPAdapter
adapter = HTTPAdapter(max_retries=retry_strategy)
session = requests.Session()
session.mount("http://", adapter)
session.mount("https://", adapter)
Java(使用 Spring Retry 或 OkHttp)
// Spring Retry(基于注解)
@Service
public class MyService {
@Retryable(
value = {TimeoutException.class, ServiceUnavailableException.class},
maxAttempts = 3,
backoff = @Backoff(delay = 2000, multiplier = 2.0, jitter = 1000) // 2s, 4s, 8s
)
public MyResponse callExternalApi() {
// ...
}
@Recover
public MyResponse recover(TimeoutException e) {
// 所有重试失败后的降级逻辑
return new MyResponse("fallback");
}
}
// OkHttp
OkHttpClient client = new OkHttpClient.Builder()
.retryOnConnectionFailure(true)
.connectTimeout(10, TimeUnit.SECONDS)
.readTimeout(10, TimeUnit.SECONDS)
.addInterceptor(new RetryInterceptor(3)) // 自定义或使用 okhttp-retry
.build();
Go(使用特定库)
import (
"time"
"github.com/avast/retry-go/v4"
)
func FetchData(url string) error {
return retry.Do(
func() error {
resp, err := http.Get(url)
if err != nil {
return err
}
defer resp.Body.Close()
if resp.StatusCode >= 500 {
return fmt.Errorf("server error: %d", resp.StatusCode)
}
return nil
},
retry.Attempts(3),
retry.Delay(1 * time.Second),
retry.DelayType(retry.BackOffDelay), // 指数退避
retry.RetryIf(func(err error) bool {
// 只对 5xx 和网络错误重试
return true
}),
)
}
消息队列 (Kafka, RabbitMQ)
Kafka(消费者端)
# consumer.properties 配置 # 自动重试(内部机制,不要和手动提交混合使用) enable.auto.commit=false # 建议手动提交 max.poll.interval.ms=300000 # 消费处理超时时间,超时自动重平衡 retry.backoff.ms=100 # 发送消息失败后的重试间隔 # 手动重试:抛出异常或显式调用 nack 让消息回到队列
RabbitMQ(消费者端)
// Spring AMQP 重试配置
@Bean
public SimpleRabbitListenerContainerFactory rabbitListenerContainerFactory(
ConnectionFactory connectionFactory) {
SimpleRabbitListenerContainerFactory factory = new SimpleRabbitListenerContainerFactory();
factory.setConnectionFactory(connectionFactory);
// 配置重试
RetryInterceptorBuilder<?> builder = RetryInterceptorBuilder.stateless();
builder.maxAttempts(3); // 重试次数(包含第一次)
builder.backOffOptions(1000, 2.0, 10000); // 初始间隔1s,倍数2,最大间隔10s
// 设置拒绝策略:重试完仍失败则进入死信队列(推荐)
factory.setAdviceChain(builder.build());
// 死信队列配置:在队列参数中配置 x-dead-letter-exchange
factory.setDefaultRequeueRejected(false); // 拒绝消息死信而不是丢弃
return factory;
}
数据库连接池 (HikariCP, DBCP2)
// HikariCP(Spring Boot 默认连接池) spring.datasource.hikari.connection-timeout=10000 # 等待连接池分配连接的超时时间 spring.datasource.hikari.max-lifetime=1800000 # 连接最大存活时间 spring.datasource.hikari.leak-detection-threshold=60000 // 注意:数据库操作的重试通常不在连接池层配置,而是在框架层(如 MyBatis 或 JPA 的重试插件) // 连接池本身不提供 SQL 级别的重试
云服务 SDK (AWS, Azure, Google Cloud)
大多数云SDK内置了重试机制,只需配置参数即可。
AWS SDK v2 for Java / Python
# Java SDK 2.x (通过 credentials profile 或 builders 配置)
aws.retry.mode=adaptive # 或 legacy (standard)
aws.maxAttempts=3
# 自适应重试模式会根据服务端节流动态调整
# Python boto3
import boto3
from botocore.config import Config
config = Config(
retries = {
'max_attempts': 10,
'mode': 'adaptive' # 或 'standard'
}
)
client = boto3.client('s3', config=config)
Azure SDK for .NET/Java
// .NET
var retryOptions = new RetryOptions
{
Mode = RetryMode.Exponential,
Delay = TimeSpan.FromSeconds(0.8),
MaxRetries = 3,
MaxDelay = TimeSpan.FromSeconds(10),
NetworkTimeout = TimeSpan.FromSeconds(100)
};
var options = new BlobClientOptions();
options.Retry = retryOptions;
一个完整的通用配置示例(伪代码)
# 通用重试策略配置(适合用配置文件管理)
retry:
enabled: true
max_attempts: 3 # 总尝试次数(第1次+2次重试)
interval_strategy: "exponential_backoff_with_jitter" # 指数退避+抖动
initial_interval_ms: 1000 # 第一次重试前等待1秒
multiplier: 2.0 # 翻倍
max_interval_ms: 10000 # 最长等待10秒
jitter_range_ms: [500, 2000] # 随机抖动范围
only_retry_on:
- 5xx # 服务端错误
- TIMEOUT # 网络超时
- CONNECTION_ERROR
do_not_retry_on:
- 4xx # 客户端错误
- 403 # 禁止访问
- 409 # 冲突(幂等性问题)
避坑指南
- 幂等性:只有你的操作是幂等的(重复执行结果相同)才能放心重试,例如支付扣款接口绝对不能无脑重试,否则可能重复扣款。
- 熔断配合:如果服务已经崩溃(连续返回 503),单纯的指数退避依然会打满重试次数,建议配合 熔断器 (Circuit Breaker) — 达到一定错误率后直接快速失败。
- 最终一致性:对于关键任务,重试有上限,超出上限后请写入死信队列、日志或告警,由人工或后续补偿流程处理。
- 不要重试太快:最小间隔建议 500ms,太短的重试等于 DDoS 攻击。
配置重试策略时,核心是选对重试条件(只对临时性错误重试)、用指数退避+抖动(保护下游)、设置最大次数上限(防无限循环)、结合熔断器(防雪崩),没有一种配置适合所有场景,最好在测试环境中压测调优。