限流发生时,最危险的动作往往是立刻重试。脚本被拒绝后,已抓到的数据还在内存或临时文件里,如果程序直接退出或反复请求,已有结果可能丢失,还可能把限流窗口拖得更长。保护已有结果的核心是:先落盘、再判断、后补量。下面按一个矛盾现象、两种解释和可区分证据展开。
脚本跑了一半被限流,日志里出现大量失败记录,直觉会认为整批结果都不可信。但限流只说明调用频率或配额触发了限制,并不自动否定此前已经成功返回的内容。真正需要区分的是:失败发生在请求层,还是发生在结果处理层。
如果脚本在收到响应后先做校验再写入,那么已写入的部分通常带有完整字段;如果脚本是全部跑完才统一写文件,那么限流中断可能让内存中的结果一起消失。这个差别决定了你该先抢救数据,还是先调整调用节奏。
同一脚本在降低并发、增加间隔后能继续返回正常结果,说明限制与单位时间内的调用密度有关。此时已有结果仍然可用,只需改变请求节奏,不必重跑全部任务。
如果降低频率后仍然持续被拒,或者返回内容从完整数据变成错误提示、空结果,那么问题可能不在节奏,而在配额上限、凭证状态或接口调用方式。此时继续重试意义不大,已有结果也需要重新核对适用范围。
这两种解释对应的处理方向完全不同:前者是调度问题,后者是资格或配置问题。把后者当前者处理,会浪费大量等待时间。
第一步是让脚本具备断点写入能力:每成功处理一条或一小批,就把结果追加到本地文件,并记录对应的任务标识。这样限流中断后,已成功部分不会随进程退出而消失。
第二步是分离“已获取”和“已确认”两种状态。已获取指接口返回了内容,已确认指内容通过了字段校验和去重检查。限流后先统计这两类数量,再决定补量范围。假设一批任务共一千条,已获取六百条,其中通过校验五百条,那么补量应优先覆盖剩余四百条,而不是全部重跑。这个数字只是说明比较方法,实际比例以你的日志为准。
第三步是给重试设置上限和退避间隔。达到上限后停止请求,输出未完成清单,交由人工判断是换时间窗口、调整凭证,还是缩小任务范围。这个动作的结果会直接影响下一步:如果退避后能继续,就按断点补量;如果持续失败,就转入配置排查,不再消耗调用次数。
当旧脚本或旧合作关系需要退出时,不必把所有历史结果一起丢弃。可以保留三类内容:已通过校验且字段完整的结果、能说明数据来源和获取时间的记录、以及未完成任务的标识清单。前两类支撑后续复用,第三类避免重复劳动。
需要谨慎对待的是只完成一半、字段缺失或来源不明的记录。它们看似节省了重新获取的成本,却可能在后续合并时引入难以排查的差异。判断标准不是数量多少,而是能否说清每条结果对应哪个任务、哪个时间点、哪种调用方式。说不清的部分,保留价值有限。
最后,把限流处理写成可重复执行的流程,而不是依赖某次临时操作。这样下次遇到同类中断时,已有结果的保护动作是确定的,补量范围也有据可查。