报错是这么冒出来的。消息队列积压到 3 万条后把消费者从 8 个扩到 40 个,上游立刻开始 429,实际吞吐只涨了两成,积压反而因为重试涨到 5 万。
中间走过弯路,把「消费者并发高但单条处理变慢,上下文切换变多」当成主因,改完现象没变。
原因不止一个,得分开看。扩容没有和上游的速率限制联动。另一种情况是429 之后整批重投,重复消费把压力放大。
还有一种情况,缺少全局速率闸门,每个消费者各自限自己的。
量出上游可承受的稳定 QPS
python bench_upstream.py --ramp 5,10,20,40 --step-s 60
然后在消费者侧加全局令牌桶
python -c "print({'rate':18,'burst':30})"
接着扩容前先看单条处理耗时分布
python -c "import json;d=json.load(open('lat.json'));print(len(d))"
等前面都确认过,再按令牌桶上限重放积压并观察 429
python replay_queue.py --limit 18 --file backlog.jsonl
恢复的判定其实很直接。消费者保持 12 个时积压开始下降,429 比例从 23% 降到 1% 以内,端到端延迟稳定在 40 秒左右。
积压时先看上游能不能吃下,扩容只是把队列压力搬到接口上;速率闸门要全局共享,不然每个消费者都觉得自己很节制。监控比日志更早给出信号,事后回看经常能提前半小时发现异常。
