基于CLIENT-KEY头的Nginx限流配置问题:如何实现10r/m限流?
解决方案
问题根源
当前配置中limit_req_zone的rate=1r/m是每分钟生成1个令牌,配合burst=9的令牌桶容量,总共允许10个请求后触发限流,但后续每分钟仅补充1个令牌,导致恢复后只能每分钟发送1个请求,与预期的10r/m不符。
基础调整配置(实现10r/m限流,超出即拒绝)
# 按CLIENT-KEY头设置限流区域,每分钟生成10个令牌,区域容量10m limit_req_zone $http_CLIENT_KEY zone=newzone:10m rate=10r/m; server { listen 80; location / { # 启用限流,禁用突发请求缓冲,超出直接返回429 limit_req zone=newzone burst=0 nodelay; limit_req_status 429; proxy_pass http://127.0.0.1:8080; } }
配置说明
rate=10r/m:核心修正项,设置每个CLIENT-KEY每分钟允许10个请求,令牌桶每分钟自动生成10个令牌。burst=0:关闭突发请求缓冲,一旦请求数超出每分钟10个的限制,直接返回429状态码;若需允许短时间内的突发请求,可将burst设为10并保留nodelay,但此时不会完全封禁,而是按10r/m的速率逐步恢复请求能力。
进阶配置(实现超出后强制封禁1分钟)
如果需要严格实现"超出10r/m后,1分钟内所有请求都被拒绝"的效果,仅靠原生limit_req模块无法直接完成,需结合OpenResty的Lua模块实现:
limit_req_zone $http_CLIENT_KEY zone=newzone:10m rate=10r/m; # 存储封禁时间的共享内存区域 lua_shared_dict limit_req_block 10m; server { listen 80; location / { # 检查是否处于封禁期 access_by_lua_block { local client_key = ngx.var.http_CLIENT_KEY local block_time = ngx.shared.limit_req_block:get(client_key) if block_time and block_time > ngx.now() then return ngx.exit(429) end } # 限流判断,超出时触发封禁逻辑 limit_req zone=newzone burst=0 nodelay; limit_req_status 429; # 捕获限流状态,设置1分钟封禁 error_page 429 = @block; proxy_pass http://127.0.0.1:8080; } location @block { access_by_lua_block { local client_key = ngx.var.http_CLIENT_KEY if client_key then # 设置封禁时长为1分钟(60秒) ngx.shared.limit_req_block:set(client_key, ngx.now() + 60) end return ngx.exit(429) } } }
该配置通过共享内存记录超限的CLIENT-KEY封禁时间,实现超出限制后1分钟内拒绝所有请求的效果。
内容的提问来源于stack exchange,提问作者Amirhossein Shaerpour
相关产品推荐
相关产品推荐

