先看现象。自研令牌桶用 float 每毫秒累加一次速率,跑五小时后实际放行比理论少 300 个请求,日志里 tokens 一直是 99.99998 这种值。
排查方向其实有限,先把可能性排一排。浮点累加的舍入误差不断累积。另一种情况是补充频率过高 每次加的量小于精度。
还有一种情况,用时间差乘速率而不是整数刻度。
另外,没有周期性归零或对账。
第一件事是验证误差有多大
python -c "print(sum([0.001]*100000))"
随后改成整数微令牌按纳秒补齐
python bucket.py --unit micro --precision int
接着按时间差一次性补齐而不是每毫秒加
python bucket.py --fill-on-demand
等前面都确认过,再加对账日志比对放行数
python rate_audit.py --window 5h
当时还开着另一个排查窗口,两边日志对照着看才定位到。
恢复的判定其实很直接。五小时内放行数与理论值偏差小于 0.1%,令牌余量不再出现浮点尾数。
提醒一点。限流器要用整数计数,浮点累加在长时间运行下必然漂移。如果同一现象隔几天又出现,说明根因没找到,别当偶发处理。
