7.9.2 LuaJIT与ngx_lua基础
LuaJIT与ngx_lua基础#
LuaJIT 是 OpenResty 的高性能 Lua 运行时,配合 ngx_lua 可在 Nginx 事件驱动模型中执行 Lua 代码,实现高并发下的动态逻辑处理。本节从执行模型、阶段与 API、可运行示例、安装与排错、练习任务展开。
原理草图:Nginx 事件模型与 Lua 阶段#
运行环境与执行模型#
- LuaJIT 特性:JIT 编译、FFI 接口、低开销协程,适合高并发场景的轻量逻辑。
- ngx_lua 机制:将 Lua 代码嵌入 Nginx 指令中,在不同阶段(phase)执行。
- 事件驱动:非阻塞 I/O 为核心,阻塞操作会导致性能下降或请求堆积。
Nginx 阶段与执行上下文示例#
# /usr/local/openresty/nginx/conf/nginx.conf
worker_processes 1;
events { worker_connections 1024; }
http {
lua_shared_dict metrics 10m;
server {
listen 8080;
rewrite_by_lua_block {
ngx.var.request_id = ngx.var.request_id or ngx.time()
}
access_by_lua_block {
local dict = ngx.shared.metrics
local key = ngx.var.remote_addr
local n = dict:incr(key, 1, 0)
if n > 100 then
return ngx.exit(429)
end
}
content_by_lua_block {
ngx.header["Content-Type"] = "application/json"
ngx.say('{"ok":true,"id":"', ngx.var.request_id, '"}')
}
log_by_lua_block {
ngx.log(ngx.INFO, "req_id=", ngx.var.request_id)
}
}
}
常用 API 与关键对象示例#
-- /usr/local/openresty/nginx/lua/hello.lua
local args = ngx.req.get_uri_args()
local name = args.name or "world"
ngx.status = 200
ngx.header["Content-Type"] = "text/plain"
ngx.say("hello ", name)
-- 共享字典计数
local dict = ngx.shared.metrics
local count = dict:incr("hello_count", 1, 0)
ngx.say("count=", count)
在配置中引用模块文件:
# /usr/local/openresty/nginx/conf/nginx.conf
http {
lua_package_path "/usr/local/openresty/nginx/lua/?.lua;;";
lua_shared_dict metrics 10m;
server {
listen 8080;
location /hello {
content_by_lua_file /usr/local/openresty/nginx/lua/hello.lua;
}
}
}
安装与验证(OpenResty + LuaJIT)#
以 CentOS 7/8 为例,可替换为对应发行版仓库。
# 1) 安装依赖
yum install -y yum-utils gcc gcc-c++ make pcre pcre-devel zlib zlib-devel openssl openssl-devel
# 2) 添加 OpenResty 仓库
yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
# 3) 安装 OpenResty(含 LuaJIT)
yum install -y openresty
# 4) 启动并检查版本
/usr/local/openresty/nginx/sbin/nginx -v
/usr/local/openresty/bin/openresty -V
/usr/local/openresty/bin/luajit -v
验证示例:
# 载入配置并启动
/usr/local/openresty/nginx/sbin/nginx -t
/usr/local/openresty/nginx/sbin/nginx
# 访问测试
curl -i "http://127.0.0.1:8080/hello?name=ops"
预期输出:
HTTP/1.1 200 OK
Content-Type: text/plain
hello ops
count=1
关键命令解释#
nginx -t:检测配置语法,避免因语法错误导致启动失败。nginx -s reload:平滑重载配置,不中断现有连接。openresty -V:查看编译选项与模块,确认 ngx_lua 是否启用。luajit -v:确认 LuaJIT 版本是否可用。
性能与稳定性注意事项(可操作)#
- 避免阻塞:禁止在
content_by_lua中执行os.execute或同步网络 I/O。 - 共享缓存:使用
lua_shared_dict保存计数与热点数据。 - 代码热更新:
lua_code_cache on;(生产开启),开发调试可临时关闭。 - 内存限制:共享字典大小不足会导致
no memory错误。
排错清单(含命令)#
- 启动失败:unknown directive "content_by_lua_block"
- 原因:未使用 OpenResty 或未编译 ngx_lua
- 解决:
bash /usr/local/openresty/bin/openresty -V | grep -i lua - 访问 500:attempt to call global 'ngx' (a nil value)
- 原因:在纯 Lua 环境执行了 ngx API
- 解决:只在 Nginx/Lua 阶段执行脚本 - 共享字典不足:no memory
- 解决:
nginx lua_shared_dict metrics 50m; - 热更新不生效
- 原因:lua_code_cache on缓存代码
- 解决:开发环境临时关闭并 reload
nginx lua_code_cache off;
练习任务#
- 限流练习:将
access_by_lua_block改为 1 分钟内 20 次限流(使用ngx.now()+ shared dict 计数)。 - 鉴权练习:在
access_by_lua_block中校验请求头X-Token,失败返回 401。 - 日志练习:在
log_by_lua_block中输出响应耗时ngx.now() - ngx.req.start_time()。
小结#
通过 LuaJIT 与 ngx_lua 的执行阶段、API 与配置方式,可以在 Nginx 内实现轻量级网关逻辑。结合安装、验证、排错和练习,可以快速形成可运行的开发与运维闭环。