可在nginx边缘层用lua脚本实现秒杀场景实时拦截:通过redis校验用户是否已抢购、滑动窗口限流(如100ms内每用户每商品仅1次)、共享内存读取库存状态(≤0则返503)、ip频控封禁等多维动态准入判断,全部逻辑在access_by_lua_block中快进快出执行。

用Nginx+Lua在边缘做实时请求拦截
秒杀场景下,99%的请求其实不该到达后端——它们来自脚本、重复点击或已抢完仍刷屏的用户。把过滤逻辑下沉到边缘Nginx层,用Lua做轻量级决策,能瞬间挡掉无效流量,避免压垮下游服务。
基于请求特征的动态准入判断
不依赖固定黑名单或简单QPS限流,而是结合多个实时维度做综合判定:
- 用户标识校验:从Cookie、Header或Token中提取user_id或device_id,查Redis缓存确认是否已抢成功(setnx写入成功即为首次抢购)
- 接口级速率控制:用lua-resty-limit-traffic按user_id或商品ID做毫秒级滑动窗口计数(例如100ms内最多1次请求)
- 活动状态同步感知:Lua中调用本地HTTP接口或读取共享内存(shm)获取秒杀开关、库存余量,余量≤0直接返回503
- 行为异常识别:对同一IP短时间高频请求(如1s内≥5次),自动升级为临时封禁(写入redis并设置60s过期)
关键Lua代码结构示例
在nginx.conf的location块中嵌入access_by_lua_block:
access_by_lua_block {
local redis = require "resty.redis"
local limiter = require "resty.limit.count"
local red = redis:new()
red:set_timeout(100)
red:connect("127.0.0.1", 6379)
<pre class="brush:php;toolbar:false;">local user_id = ngx.var.cookie_user_id or ngx.var.arg_uid
local item_id = ngx.var.arg_item_id
-- 库存检查(从共享内存或redis读)
local stock = tonumber(red:get("stock:" .. item_id)) or 0
if stock <p>}</p>部署与稳定性要点
边缘节点资源有限,Lua逻辑必须“快进快出”:
- 所有Redis操作设超时(≤100ms),失败时降级为放行或默认拒绝,不阻塞Nginx事件循环
- 避免在access阶段做耗时IO或复杂计算;校验逻辑尽量用shared_dict缓存中间结果(如活动开关、热商品库存)
- 用lua-resty-lock控制共享字典更新竞争,防止缓存击穿时大量请求穿透到后端
- 通过OpenResty的lua_shared_dict + 定时worker进程(timer)实现库存的异步预热与定期刷新











