Retryer
Retryer 是 Agents-Flex 内置的通用重试执行器,提供可配置的重试策略、退避机制和异常过滤器。该组件适用于所有需要稳定性保障的场景,如网络请求、大模型 API 调用、数据库操作等。
Retryer 设计为线程安全、可复用,并提供构建式 API 方便开发者灵活扩展。
1. 核心概念
1.1 重试(Retry)
在执行某项任务失败时,根据预设策略自动再次执行,用于提升系统稳定性与容错能力。
1.2 重试条件
Retryer 支持基于两类条件触发重试:
- 异常(Exception Predicate):发生指定类型的异常时重试
- 返回结果(Result Predicate):当结果不满足条件时重试(如响应为空、code 非 200 等)
1.3 退避(Backoff)
为避免短时间大量重试导致雪崩,Retryer 支持:
- 固定延迟(Fixed Delay)
- 指数退避(Exponential Backoff)
- 最大延迟限制(Max Delay)
- 全局超时时间(Total Timeout)
1.4 可复用性与线程安全
Retryer 本身无状态,可在应用中作为单例复用(例如用于 API 调用统一策略)。
2. 使用场景
Retryer 常用于以下场景:
调用外部 API
网络波动、超时、偶发 500 错误等可通过重试平滑掉。
调用大语言模型(LLM)服务
LLM API 高并发下可能出现 timeout 或 rate limit,适合在 SDK 中统一加重试。
消息队列 / RPC 调用
防止瞬时网络抖动导致消息处理失败。
数据库访问
连接池偶发重置或瞬时阻塞,可以重试。
IO 操作(文件、S3、OSS)
对临时异常的容错。
3. 快速入门
Retryer 提供两种使用方式:
3.1 快速静态方法(推荐入门)
Callable 重试
String result = Retryer.retry(
() -> httpClient.get("https://api.example.com/data"),
3,
200
);含义:
- 最多重试 3 次
- 初始延迟 200ms(固定)
Runnable 重试
Retryer.retry(
() -> System.out.println("Retry test"),
3,
100
);3.2 完整构建器(Builder)
Retryer retryer = Retryer.builder()
.maxRetries(5)
.initialDelayMs(200)
.exponentialBackoff()
.maxDelayMs(5000)
.operationName("fetch-user")
.build();
String result = retryer.execute(() -> fetchUser("123"));4. 配置说明与进阶用法
以下为 Retryer 的全部可配置项及其作用。
4.1 最大重试次数(maxRetries)
.maxRetries(3)总执行次数为 maxRetries + 1(含首次执行)。 默认值:2
4.2 初始延迟(initialDelayMs)
.initialDelayMs(200)首次失败后的延迟,默认 100ms。
4.3 最大延迟(maxDelayMs)
.maxDelayMs(5000)在指数退避模式下用作上限。
4.4 启用指数退避(exponentialBackoff)
.exponentialBackoff()延迟增长公式:
delay(n) = min(initialDelay * 2^n, maxDelay)用于防止雪崩,推荐网络调用开启。
4.5 全局超时(totalTimeoutMs)
.totalTimeoutMs(8000)超过总耗时会直接停止重试并抛异常。
4.6 基于异常的重试条件(retryOnException)
默认规则为常见网络异常:
- SocketTimeoutException
- ConnectException
- UnknownHostException
- IOException
也可自定义:
.retryOnException(e -> e instanceof MyBizException)4.7 基于结果的重试条件(retryOnResult)
.retryOnResult(result -> result == null || result.equals("ERROR"))常用于:
- HTTP 响应异常
- 业务 code 不为 0
- LLM 输出为空
4.8 操作名称(operationName)
用于日志定位:
.operationName("sync-user-info")5. 高级用法
5.1 结合 LLM API 使用(推荐)
Retryer retryer = Retryer.builder()
.maxRetries(4)
.exponentialBackoff()
.initialDelayMs(300)
.retryOnException(e -> true) // 所有异常都重试
.retryOnResult(r -> r == null || ((String) r).isBlank())
.operationName("llm-completion")
.build();
String resp = retryer.execute(() -> llmClient.chat(prompt));适合 Agents-Flex 与 OpenAI/阿里/字节等模型统一重试策略。
5.2 重试直到业务成功
.retryOnResult(r -> ((ApiResponse)r).getCode() != 0)5.3 与分布式任务结合
将 Retryer 作为全局单例:
public static final Retryer API_RETRY = Retryer.builder()
.maxRetries(3)
.exponentialBackoff()
.build();供整个系统共享。
5.4 重试 Runnable(无返回)
retryer.execute(() -> syncToDB(user));6. 核心组件解释
Retryer 内部包含以下关键组件:
6.1 Builder
用于构建配置,不包含执行逻辑。
6.2 Retryer
核心执行器:
- 控制执行循环
- 控制重试条件
- 实现退避逻辑
- 管理超时
- 捕获最终异常
6.3 Predicates
用于判定是否需要再次重试:
- retryOnException
- retryOnResult
6.4 RetryException
当超过最大重试次数,或超时触发,抛出该异常。
7. 源码解析(逐段说明)
以下为关键执行逻辑概念解读。
7.1 重试主循环
for (int attempt = 0; attempt <= maxRetries; attempt++) { ... }执行次数 = maxRetries + 1(含首次尝试)。
7.2 处理返回结果触发重试
if (attempt < maxRetries && retryOnResult.test(result)) {
sleep...
continue;
}7.3 处理异常触发重试
catch (Exception e) {
if (attempt < maxRetries && retryOnException.test(e)) {
sleep...
} else {
break;
}
}7.4 指数退避实现
currentDelay = Math.min(currentDelay * 2, maxDelayMs);7.5 全局超时控制
long deadline = now + totalTimeoutMs;
if (currentTime > deadline) throw TimeoutException;7.6 安全睡眠(可中断)
TimeUnit.MILLISECONDS.sleep(sleepMs);