共计 1725 个字符,预计需要花费 5 分钟才能阅读完成。
问题背景
在分布式系统中,类似 Claude 这样的 AI 服务出现 ’temporary service’ 提示是典型的中断场景。与永久性故障不同,临时中断通常具有以下特征:

- 持续时间较短(分钟级到小时级)
- 服务端返回明确的错误码(如 HTTP 503)
- 可能伴随自动恢复通知
- 局部性影响(特定 region 或部署单元)
这类中断对业务链路的冲击主要体现在:
- 同步调用场景下的请求堆积
- 异步任务消费延迟增长
- 依赖服务出现级联故障风险
技术方案对比
应对服务中断主要有三种技术路线:
- 轮询检测 :适合维护成本敏感的非关键业务
- 实现简单但响应延迟高
-
可能加重服务端负载
-
Webhook 通知 :适合事件驱动架构
- 实时性最好
-
需要额外维护通知通道
-
熔断降级 :推荐用于生产级系统
- 结合主动探测和被动防御
- 支持多级降级策略
选择指数退避算法的核心依据:
- 数学证明是分布式系统最优重试策略
- 内置 Jitter 可避免客户端同步震荡
- 与熔断器模式天然兼容
核心实现(Go 示例)
type RetryController struct {
maxAttempts int
baseDelay time.Duration
metrics *prometheus.CounterVec
mu sync.Mutex
attempts int
}
func (rc *RetryController) Do(ctx context.Context, fn func() error) error {
for {err := fn()
if err == nil {return nil}
rc.mu.Lock()
rc.attempts++
if rc.attempts >= rc.maxAttempts {rc.mu.Unlock()
return fmt.Errorf("max retries exceeded")
}
rc.mu.Unlock()
delay := rc.calculateDelay()
select {case <-time.After(delay):
case <-ctx.Done():
return ctx.Err()}
}
}
func (rc *RetryController) calculateDelay() time.Duration {jitter := rand.Float64() * 0.3 // 30% 抖动系数
multiplier := math.Pow(2, float64(rc.attempts))
delay := float64(rc.baseDelay) * multiplier * (1 + jitter)
return time.Duration(delay)
}
关键设计点:
- 使用 sync.Mutex 保证并发安全
- 通过 context 支持调用链取消
- 动态计算包含随机抖动的退避时间
- 暴露 Prometheus 指标监控重试分布
生产级增强
熔断器实现
推荐采用三段式状态机:
- 闭合状态:正常请求
- 断开状态:直接拒绝请求
- 半开状态:试探性放行部分请求
降级策略
- 功能降级:关闭非核心特性
- 数据降级:返回缓存或默认值
- 必须保持 API 版本兼容性
日志规范
{
"timestamp": "2023-07-20T14:30:00Z",
"service": "claude-proxy",
"attempt": 3,
"delay_ms": 1200,
"error": "service unavailable"
}
避坑指南
-
线程池耗尽 :所有重试请求必须设置超时
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() -
重试风暴 :
- 集群维度共享重试计数器
-
采用随机化重试时间窗口
-
状态不一致 :
- 实现基于版本号的缓存失效
- 定期同步服务端状态 API
延伸思考
- 跨 region 故障转移需要解决:
- 数据同步延迟问题
- 全局负载均衡策略
-
终端用户路由一致性
-
客户端 SDK 透明重试要点:
- 自动识别可重试错误码
- 请求幂等性保证
-
重试预算限制
-
服务恢复后校验:
- 增量数据比对
- 最终一致性检查
- 补偿事务机制
实践总结
这套方案在我们电商推荐系统稳定运行超过 18 个月,成功处理了包括 Claude 在内的多个第三方服务中断事件。核心收获是:容灾设计需要在成本和可靠性之间找到平衡点,而良好的可观测性是一切自动化处理的基础。建议开发者根据自身业务 SLA 需求,灵活调整文中提到的参数阈值。
正文完
