先看现象。给推理网关配了每实例 5 QPS 的本地令牌桶,压测时 20 个 Pod 合计打到 100 QPS,上游 429 不断,而配置里明明写着全局上限 5。
排查方向其实有限,先把可能性排一排。限流器是进程内计数,副本之间不共享。也可能是网关层与业务层各限一次,数值叠加。
不容易想到的是,令牌桶按请求数计,流式请求被算成一次。
还有一种情况,扩缩容后新 Pod 带着满桶上线。
测单实例与全集群的实际 QPS
python -c "print('per-pod 5 qps, pods 20, total 100 qps')"
接着把限流计数挪到 Redis 做全局窗口
redis-cli --eval rate_limit.lua global:llm , 5 1
再往下配置网关侧统一限流并关闭业务侧
kubectl set env deploy/gateway RATE_LIMIT_ENABLED=false
压测确认总 QPS 稳定在上限内
hey -z 60s -q 20 -c 10 https://api.example.com/v1/chat
恢复的判定其实很直接。全集群总 QPS 稳定在 5 附近,上游 429 归零,扩缩容时新 Pod 不会带来流量尖峰。
这里还有个坑。本地限流只在单实例有意义,多副本部署必须换集中式计数,否则副本数就是倍数,扩容等于放大违规流量。改动前把原配置备份一份,出问题能马上回滚,这比任何技巧都实用。
