尧图建网站 尧图建网站 YAOTU WEB BUILD 免费咨询
ARTICLE DETAIL

资讯详情

深耕网站建设与建站编程的一线实战洞察。

提示词重试的边界

提示词重试的边界 提示词重试的边界设想上游 API 短暂抖动少数慢请求若同时触发固定次数的立即重试就会放大并发和队列压力。重试机制需要限额、退避与熔断而不是把“重试 3 次”当作默认答案。1. 供应商 API 抖动 30 秒客户端无脑重试把请求队列彻底打爆很多系统在对接 LLM API 时重试逻辑写得非常简单粗暴捕获到 Timeout 异常立刻for i in range(3)无脑发起重试。当供应商 API 发生短暂卡顿时大量积压的请求在固定时间点同时触发重试。原本 100 QPS 的正常流量在重试叠加下陡增到 400 QPS。正常状态: [流量 100 QPS] ── [LLM API Server] (稳定) 网络抖动: [流量 100 QPS] ── [LLM API 卡顿 5s] 盲目重试: [原始 100 QPS 重试 300 QPS] ── [LLM API Server 彻底崩塌]这股突发流量被称为“重试风暴Retry Storm”。它会像海啸一样冲毁下游原本就已经很脆弱的 API 服务端引发连锁雪崩。2. 破除同频共振带随机抖动Jitter的指数退避重试机制要消除重试风暴核心是破坏客户端之间的“同频共振”。第一步是放弃固定间隔重试改用指数退避Exponential Backoff。重试等待时间随着失败次数的增加呈指数级增长例如 1s, 2s, 4s, 8s。第二步也是最关键的一步是加入随机抖动Full Jitter。在计算出的指数退避时间基础上乘以一个 0 到 1 之间的随机因子。退避公式: WaitTime Random(0, Min(MaxWait, Base * (2 ^ attempt)))通过引入随机性成百上千个并发客户端的重试时间点被均匀分散在轴线上彻底打碎了集群重试的峰值波谷。3. 服务端保护网结合滑动窗口断路器Circuit Breaker停止无效挂起仅仅在客户端做退避还不够。如果供应商 API 已经完全宕机例如返回 503 或持续连接拒绝继续进行任何重试都是毫无意义的资源消耗。必须在请求链路上挂载滑动窗口断路器Circuit Breaker。断路器监控过去 10 秒内的请求失败率。如果失败率超过 50%断路器立刻切换为OPEN状态后续所有请求直接在本地“快速失败Fast Fail”不再向外发起真实网络调用为下游供应商争取宝贵的恢复时间。4. 面向生产环境的带 Jitter 退避与熔断器的 LLM 重试器代码以下是专为 LLM API 调用打造的面向生产环境的客户端内置了 Full Jitter 指数退避算法以及滑动窗口熔断器。import time import random import math from typing import Callable, Any, Tuple class CircuitBreakerOpenException(Exception): pass class LLMResilientClient: def __init__( self, max_retries: int 3, base_delay: float 1.0, max_delay: float 10.0, failure_rate_threshold: float 0.5, window_size: int 10 ): self.max_retries max_retries self.base_delay base_delay self.max_delay max_delay self.failure_threshold failure_rate_threshold self.window_size window_size self.window_history [] # 存储最近的请求结果 (True/False) self.is_open False self.open_time 0.0 self.cooldown 5.0 # 熔断冷却 5 秒 def _calculate_jitter_delay(self, attempt: int) - float: 计算带 Full Jitter 的指数退避等待时间 calculated_delay self.base_delay * (2 ** attempt) capped_delay min(self.max_delay, calculated_delay) # Full Jitter: 在 0 到 capped_delay 之间随机取值 sleep_time random.uniform(0, capped_delay) return sleep_time def _record_result(self, success: bool): self.window_history.append(success) if len(self.window_history) self.window_size: self.window_history.pop(0) if len(self.window_history) self.window_size: failures self.window_history.count(False) rate failures / len(self.window_history) if rate self.failure_threshold: self.is_open True self.open_time time.time() print(f【告警】滑动窗口失败率达 {rate*100:.1f}%熔断器打开) def execute_with_retry(self, api_func: Callable[[], Any]) - Tuple[bool, Any, str]: # 校验熔断器状态 if self.is_open: if time.time() - self.open_time self.cooldown: print(【熔断器】冷却结束进入半开试探状态...) self.is_open False self.window_history.clear() else: raise CircuitBreakerOpenException(Circuit breaker is OPEN. Fast fail triggered.) for attempt in range(self.max_retries 1): try: result api_func() self._record_result(True) return True, result, fSuccess on attempt {attempt} except Exception as e: print(f请求失败 (Attempt {attempt}/{self.max_retries}): {str(e)}) if attempt self.max_retries: self._record_result(False) return False, None, fAll {self.max_retries} retries failed. sleep_duration self._calculate_jitter_delay(attempt) print(f - 退避等待 (Full Jitter): {sleep_duration:.2f}s...) time.sleep(sleep_duration) # --- 生产模拟测试 --- def unstable_llm_api(): 模拟不稳定、有概率抛出 Timeout 的 LLM 接口 if random.random() 0.7: raise TimeoutError(504 Gateway Timeout: LLM inference server busy) return LLM Response: Execution completed successfully. if __name__ __main__: client LLMResilientClient(max_retries2, base_delay0.5, max_delay3.0) print(开始模拟高并发打卡...) for req_id in range(1, 8): print(f\n--- 发起请求 #{req_id} ---) try: success, resp, msg client.execute_with_retry(unstable_llm_api) if success: print(f请求 #{req_id} 成功: {resp}) else: print(f请求 #{req_id} 最终失败: {msg}) except CircuitBreakerOpenException as err: print(f请求 #{req_id} 截断: {err}) time.sleep(0.2)5. 线上实战压测重试风暴前后的系统自愈能力比对我们在受控的压测环境中模拟了 API 供应商在 10 秒内连续丢包的情形。对比应通过对照实验确认使用固定间隔重试的旧系统在 10 秒内积压了 2400 个并发连接造成主服务 OOM 崩溃而引入了带 Jitter 的退避和滑动窗口熔断器的新系统在识别到 API 持续不可用后在第 3 秒果断切断了后续重试本地快速返回兜底回答。当 API 在第 10 秒恢复后系统自动半开探针测试并在 2 秒内恢复正常流量。确定性的重试工程设计才是保障系统自愈能力的核心支撑。
返回列表