必须用openresty替代原生nginx,因其集成luajit与常用库,支持init_by_lua_block、access_by_lua_block等阶段钩子,可实现jwt鉴权、动态路由、请求改写、限流等复杂逻辑。

直接用 OpenResty 替代原生 Nginx,再在配置中按请求阶段嵌入 Lua 逻辑,就能让 Nginx 承担鉴权、路由、改写、限流等原本需要后端服务处理的复杂业务逻辑。
必须用 OpenResty,不是标准 Nginx
原生 Nginx 不支持 Lua;OpenResty 是 Nginx + LuaJIT + 常用 Lua 库(如 resty.redis、resty.http)的一体化发行版,开箱即用。
- 从 openresty.org 下载预编译包或源码编译安装
- 验证:运行 openresty -v,输出应包含 LuaJIT 版本信息
- 配置中加 lua_package_path "/path/to/?.lua;;",方便加载自定义模块
在关键生命周期阶段写 Lua 逻辑
OpenResty 提供多个钩子,按顺序执行,各司其职:
- init_by_lua_block:master 进程启动时运行一次,适合初始化 Redis 连接池、加载全局配置表
- access_by_lua_block:进入 location 前执行,做 JWT 校验、IP 黑白名单、灰度标记
-
rewrite_by_lua_block:修改 URI 或 query 参数,比如把
/user/123改成/user?id=123 - balancer_by_lua_block:接管负载均衡选点,根据用户 ID、接口路径、节点健康状态动态决定后端地址
- content_by_lua_block:完全替代 proxy_pass,可聚合多个后端响应或返回 mock 数据
- log_by_lua_block:记录耗时、鉴权结果、路由目标等字段,不阻塞主流程
典型业务逻辑怎么写
真实可用的轻量级实现方式:
-
JWT 鉴权:解析 Authorization header 中的 token,用 resty.jwt 校验签名与 exp,失败则
ngx.exit(401) -
动态路由:读取
ngx.var.http_x_env == "canary",匹配则 set $backend_host = "canary-svc" -
简单限流:用
resty.limit.req基于 IP + redis 共享字典,每分钟最多 100 次,超限返回 503 -
请求改写:用
string.match(ngx.var.uri, "/user/(%d+)")提取 ID,再拼到 proxy_pass 的 query 中
避坑要点
生产环境不能只图功能,更要稳和快:
- 所有外部调用(Redis、HTTP)必须设
set_timeout,并用 pcall 包裹错误处理 - 避免在 access 阶段做同步 HTTP 请求;要用 cosocket 异步发请求
- 用 ngx.ctx 在同一请求的不同阶段共享数据(如鉴权后的 user_id),别用全局变量
- 高频逻辑尽量 local 缓存函数或表;大对象、死循环、os.execute 都会卡住 worker
- lua_shared_dict 用来跨请求共享状态,比如节点健康分、限流计数器











