触发速率限制时会抛出何种异常?如何确定退避重试时长?
关于速率限制异常与退避策略的问题解答
嘿,这个问题问到点子上了,我之前在对接各种API时踩过不少速率限制的坑,给你详细拆解一下:
一、速率限制达到时会抛出何种异常?
这个得看你用的工具/SDK,但核心都是和HTTP 429状态码绑定的:
- 如果是直接用HTTP请求库(比如Python的
requests、JS的fetch),通常会抛出HTTP错误异常:- Python
requests:requests.exceptions.HTTPError,捕获后可以通过response.status_code看到429 - JS
fetch:不会主动抛出异常,但返回的response.ok会是false,response.status为429
- Python
- 如果是用云服务商或平台的官方SDK(比如AWS boto3、GitHub PyGitHub),会有自定义的客户端异常:
- AWS boto3:
botocore.exceptions.ClientError,异常的response['Error']['Code']会是ThrottlingException或TooManyRequestsException - GitHub SDK:可能会抛出
github.GithubException.RateLimitExceededException这类特定异常
- AWS boto3:
简单说:不管哪种情况,本质都是告诉你“请求太频繁,被限流了”。
二、退避操作时会抛出什么异常?
其实退避是你用来应对速率限制的重试策略,它本身不会主动抛出新异常:
- 正常的退避逻辑(比如计算休眠时间、调用
sleep())如果没写错,只会暂停程序执行,不会抛出异常 - 除非你的退避代码本身有bug(比如把
Retry-After的秒数当成分钟算、休眠时被外部信号中断),才会触发其他类型的异常(比如数值错误、KeyboardInterrupt之类的)
三、发生速率限制异常时具体会出现什么情况?
分两个层面来看:
- HTTP响应层面:
- 返回状态码
429 Too Many Requests - 响应头里通常会带
Retry-After字段(告诉你多久后可以重试,值可能是秒数,比如120,或者HTTP日期格式) - 响应体里一般会有错误提示,比如
"message": "API rate limit exceeded for user xxx"
- 返回状态码
- 代码层面:
- 捕获到对应的异常(前面说的HTTP错误或SDK自定义异常)
- 异常信息里会包含状态码、错误描述,部分SDK还会附带剩余请求数、重置时间等额外信息
四、怎么知道应该休眠x分钟后再重试?
有两种可靠的方式:
- 优先用响应头的
Retry-After字段:
这是服务端直接告诉你的最佳重试时间,拿Pythonrequests举例:import requests import time try: response = requests.get("https://api.example.com/data") response.raise_for_status() except requests.exceptions.HTTPError as e: if response.status_code == 429: retry_after = int(response.headers.get('Retry-After', 60)) # 默认60秒 print(f"被限流了,{retry_after}秒后重试") time.sleep(retry_after) # 这里可以写重试逻辑 - 如果没有
Retry-After,用指数退避策略:
就是每次重试的休眠时间翻倍(比如1秒→2秒→4秒→8秒,直到设定的最大休眠时间),避免一直撞限流。很多重试库(比如Python的tenacity、JS的p-retry)都内置了这个策略,不用自己写。
内容的提问来源于stack exchange,提问作者cool breeze
相关产品推荐
相关产品推荐

