结论是:限流发生时,先不要重试,先把已经拿到的结果落盘并标记完成度,再用断点续跑替代整批重跑。这个做法成立的前提是工具返回的是可逐条对应的结构化结果;如果返回的是整页渲染后的汇总文本,或者接口在限流时直接丢弃了本次请求的全部上下文,那么落盘的对象就不是结果本身,而是需要重新界定“已完成”的边界。
脚本调用站长实用工具时,限流可能发生在三个不同位置,处理方式完全不同。
只有前两种情况下,“保住已有结果”是一个本地动作就能完成的事。第三种情况下,你保住的只是自己手里的副本,任务本身需要重新提交,而重新提交可能触发更严格的限制。判断属于哪一层,看的是返回体里有没有可对应的记录标识,而不是看错误信息写的是什么。
很多脚本在拿到结果后直接拼成一段文本或写进一个汇总文件,这在限流场景下是危险的:你无法知道哪几条已经处理、哪几条还没开始。更稳妥的做法是把每条结果写成带唯一标识的记录,同时单独维护一个进度文件。
假设一个脚本按编号列表逐条调用工具,编号范围是 1 到 500。限流在第 180 条附近出现。此时如果结果文件里每条记录都带编号,进度文件里记下“最后成功编号 179”,那么续跑时从 180 开始即可。如果结果文件只有一段合并文本,你只能从 1 重新开始,而重新开始很可能再次撞上限流。
这里的关键动作是:每次成功返回后立即追加写入,而不是等整批结束再统一保存。追加写入的代价是文件可能不完整,但换来的是任何时刻中断都不丢已完成部分。这个取舍在批量规模超过几十条时就值得做。
上面这套做法有一个明确的失效边界:当工具的结果不是逐条独立,而是依赖前后条目的上下文时,断点续跑会产生错误结果。
举例来说,假设某个查询工具在返回结果时会参考上一次查询的参数做去重或合并。第 180 条之后续跑时,脚本从 180 开始,但工具侧并不知道 1 到 179 已经查过,于是可能返回与前面重复的条目,或者因为缺少前置上下文而返回不完整的结果。此时“保住已有结果”反而制造了一份看起来完整、实际有重复或缺口的集合。
识别这种依赖的信号有几个:返回结果里出现“相对于上次”“新增”“变化”这类相对描述;工具要求按固定顺序提交;同一批请求分开执行与整体执行的结果条数不一致。只要出现其中一个,就不能简单续跑,而应该把已落盘的结果视为待校验的草稿,而不是最终结果。
确认限流层级和结果依赖关系后,按以下顺序处理:
第 3 步的判断决定了后续所有动作。逐条独立时,续跑是省成本的;不独立时,续跑只是把问题推迟到下一次限流。这个判断依据来自结果本身的结构,而不是来自限流发生的时间点或频率。
最后一点:不要用“脚本跑完了”作为完成标准,而要用“结果文件里每条都有对应记录,且记录数等于预期条数”作为标准。限流场景下,脚本正常退出和任务真正完成是两件事。把完成标准写成可核对的条件,才能在下次限流时立刻知道缺的是什么,而不是靠记忆推断。