自己实现限流要注意什么?为什么要用 Lua 脚本?限流的 key 取错了会有什么后果?这篇用自己起的 redis 与多线程,把令牌桶、原子性与伪造请求头的绕过逐个验证。
连发 7 次(序号,是否放行,需要等待秒数): [(1, True, 0.0), (2, True, 0.0), (3, True, 0.0), (4, True, 0.0), (5, True, 0.0), (6, False, 0.5), (7, False, 0.5)] 等 1.1 秒(补了约 2.2 个令牌)后连发 3 次:True, True, False(第 3 次需要再等 0.39 秒)
上一篇:Refresh Token;下一篇:CORS 预检请求。
第 76 篇讲过 Flask-Limiter 的用法,这一篇讲自己实现时的细节。
先 GET 再 SET(非原子) 放行 20 个(上限 10) Lua 令牌桶(原子,容量 10,不补充) 放行 10 个(上限 10)
redis 是自己在非默认端口起的临时实例,验证完就关掉了。
第 1 次 → 200 {'RateLimit-Limit': '3', 'RateLimit-Remaining': '2'}
第 2 次 → 200 {'RateLimit-Limit': '3', 'RateLimit-Remaining': '1'}
第 3 次 → 200 {'RateLimit-Limit': '3', 'RateLimit-Remaining': '0'}
第 4 次 → 429 {'RateLimit-Limit': '3', 'RateLimit-Remaining': '0', 'Retry-After': '1'}
第 5 次 → 429 {'RateLimit-Limit': '3', 'RateLimit-Remaining': '0', 'Retry-After': '1'}不信任代理头(用 remote_addr) 8 个请求(每个伪造不同的 X-Forwarded-For)→ [200, 200, 200, 429, 429, 429, 429, 429] ProxyFix(x_for=1) 信任 X-Forwarded-For 8 个请求(每个伪造不同的 X-Forwarded-For)→ [200, 200, 200, 200, 200, 200, 200, 200]
按 IP(未登录,3 个用户共用 1 个 IP) 9 个请求(三人轮流)→ 3 个放行,6 个 429 按用户 9 个请求(三人轮流)→ 9 个放行,0 个 429