接口返回 429 之后要等多久,重试提示该由哪一层给出
接口返回 429 之后客户端要等多久,这个重试提示该由哪一层给出?等待时长应当由服务端给出、客户端只负责遵守。规范层的定义是:429 表示客户端在给定时间窗内请求过多,属于客户端错误响应;这个响应可以带上重试提示头,用来说明客户端在再次发起请求前应当等多久。文档给出的示例值是 3600 秒,并注明其含义是该客户端在六十分钟之后可以再次请求。也就是说「多久」这件事只有服务端知道,客户端自己推算的间隔只是拿不到提示头时的兜底。
429 与 5 开头的服务端错误码不是一类
区分这两类的意义在重试策略上。5 开头的错误说明请求已经打到服务端但没能正常处理,重试间隔通常由客户端自己安排,且需要限制总次数;429 说明请求被限流规则挡下了,服务端知道窗口什么时候重新开放。
把 429 当服务端错误来处理会带来两个后果:一是重试过快,把窗口越拖越长;二是把限流当成故障,在监控里报出与实际不符的错误率。反过来,把 5 开头的错误按提示头等待也不合理,因为那类响应一般不携带等待时长。
调用接口文档里的高频能力时,客户端宜按状态码分两套逻辑:拿到 429 就遵守提示头,拿不到提示头才做指数退避;拿到服务端错误则退避并告警。
等待时长由谁决定
由服务端决定,通过响应头传递。提示头的值可以是秒数,也可以是一个具体的时间点,客户端需要两者都能解析。
服务端这一层的责任是把窗口信息如实写进响应;客户端这一层的责任是不小于这个值去重试。常见写法错误有三类:忽略提示头直接按固定间隔重试;把秒数当毫秒解析,等待时间被放大一千倍;在多个并发请求都返回 429 时各自独立重试,反而形成重试风暴。
站内接口调用建议把这条规则写成一处公共逻辑,供推送任务与导入任务共用,避免每个脚本自己实现一套等待策略。
限流按地址还是按账号两种口径
规范文档说明,限流限制通常基于客户端 IP,但当请求带认证信息或携带标识时,也可以针对具体用户或授权应用。两种口径对调用方的影响不同。
按来源地址限流时,同一出口地址上的多个任务会互相影响——批量导入跑满窗口,同机的推送任务就会拿到 429。这种情况下的正确做法不是换密钥,而是把两类任务错峰。
按登录身份或凭据限流时,情况相反:不同密钥之间的窗口互不影响,同一密钥下的所有调用共享窗口。此时应当把并发收敛到少数几个受控任务上,并为每个用途分配独立凭据,避免测试流量挤占生产窗口。
判断自己遇到的是哪一种,可以看一个信号:更换出口地址后是否恢复,或更换凭据后是否恢复。前者指向地址口径,后者指向身份口径。
退避写法与重试风暴
拿不到提示头时的兜底写法要遵守三条:起始间隔短、按倍数增长、设置上限与总次数。更重要的是在并发场景下让等待共享——一个任务收到 429 之后,同一凭据下的其他任务应当同步进入等待,而不是各自再试一次。
定时任务尤其要注意这一点。以链接推送为例,向搜索引擎推送新内容属于批量调用,任务被调度器重复触发时会出现两批请求同时打接口;正确做法是给推送任务加执行锁,并在收到 429 后由任务整体延后,而不是单条链接各自重试。
站内推送与导入接口调用怎么配合
AnQiCMS 的链接推送管理负责向搜索引擎推送新内容以加速收录,支持百度与 Bing 的主动推送;文档内容导入接口(/api/import/archive)用于批量导入,并支持按标题查询是否已存在。这两类调用的重试取向应当不同。
推送是可延迟的:这一轮没推出去,下一轮仍然有效,因此收到 429 之后整体顺延即可,不需要在单条链接上重试。导入是可中断的:批量任务在收到 429 时应当记录已完成到哪一批,按提示头等待后从断点继续,而不是整批重来;已存在判断也可以在此时顺带复核,避免重复写入。
两类调用都建议把窗口等待写成可观测的日志:本次等待多久、依据是提示头还是退避策略、哪一批被推迟。线上出现收录延迟时,这份日志比错误码更容易定位问题。
常见问题
没有返回重试提示头的 429 怎么处理?
按退避策略处理:从短间隔开始,成倍增长,设置上限次数并记录。这类情况值得反馈给接口方,因为提示头本身就是这个状态码的推荐配套信息。
客户端可以自己决定等多久吗?
可以作为兜底,但不宜作为默认。客户端不了解服务端的窗口口径,自行缩短间隔会让限流持续生效;拿到提示头时以提示头为准。
批量导入遇到 429 是不是导入失败?
不是失败,是推迟。导入任务应当保留断点,按提示头等待后继续;只有在等待上限用尽或窗口反复不放开时,才按异常处理并保留已导入位置。
推送任务要不要一直重试到成功?
不建议无限重试。推送本身可延后,重试到窗口上限就把这一批留下轮,配合执行锁避免调度器重复触发,比重试更省窗口。