7.9.4 常用模块与生态库(lua-resty-*, 第三方模块)
本节聚焦 OpenResty 常用模块与生态库的实战使用,覆盖 lua-resty-* 官方库与常见第三方模块的选型、安装、配置要点与典型场景;并提供安装命令、配置示例、排错与练习。
一、原理草图:OpenResty 模块生态与请求流
二、安装与依赖管理(opm/luarocks)
# 1) 安装 OpenResty(以 Linux 包管理为例)
sudo yum install -y openresty
# 2) 检查版本与 LuaJIT
/usr/local/openresty/bin/openresty -V
/usr/local/openresty/luajit/bin/luajit -v
# 3) 安装常用 lua-resty 库(opm)
/usr/local/openresty/bin/opm get openresty/lua-resty-core
/usr/local/openresty/bin/opm get openresty/lua-resty-lrucache
/usr/local/openresty/bin/opm get openresty/lua-resty-redis
/usr/local/openresty/bin/opm get openresty/lua-resty-http
# 4) 安装第三方库(luarocks)
/usr/local/openresty/luajit/bin/luarocks install lua-resty-openidc
/usr/local/openresty/luajit/bin/luarocks install lua-resty-session
# 5) 模块路径检查
/usr/local/openresty/luajit/bin/luajit -e 'print(package.path)'
命令解释:
- opm get 安装 OpenResty 官方库并与版本兼容。
- luarocks install 适合第三方库;建议生产使用私有镜像与版本锁定。
- openresty -V 检查编译模块,避免缺失 --with-http_ssl_module 等关键选项。
三、常用库与模块示例(含配置与预期效果)
1)lua-resty-lrucache + lua-resty-lock:本地缓存与防击穿
# /usr/local/openresty/nginx/conf/nginx.conf
worker_processes 1;
events { worker_connections 1024; }
http {
lua_shared_dict lock_dict 10m;
server {
listen 8080;
location /cache {
content_by_lua_block {
local lrucache = require "resty.lrucache"
local lock = require "resty.lock"
local cache, err = lrucache.new(200)
if not cache then ngx.say("cache init failed: ", err); return end
local key = "hot_key"
local val = cache:get(key)
if val then ngx.say("L1 hit: ", val); return end
local l = lock:new("lock_dict", {timeout=2, exptime=5})
local elapsed, err = l:lock(key)
if not elapsed then ngx.say("lock failed: ", err); return end
-- 模拟回源
val = "value_from_backend"
cache:set(key, val, 10)
l:unlock()
ngx.say("L1 miss, set: ", val)
}
}
}
}
预期效果:首次访问输出 L1 miss,后续 10 秒内输出 L1 hit。
2)lua-resty-redis:Redis 连接池与超时
location /redis {
content_by_lua_block {
local redis = require "resty.redis"
local red = redis:new()
red:set_timeouts(1000, 1000, 1000) -- 连接/读/写超时ms
local ok, err = red:connect("127.0.0.1", 6379)
if not ok then ngx.say("connect failed: ", err); return end
local res, err = red:get("foo")
if err then ngx.say("get failed: ", err); return end
red:set_keepalive(10000, 100) -- 连接池
ngx.say("redis foo: ", res)
}
}
命令解释:set_keepalive 必须执行,避免连接泄漏;set_timeouts 防止慢连接拖垮 worker。
3)lua-resty-http:外部 API 调用
location /http {
content_by_lua_block {
local http = require "resty.http"
local httpc = http.new()
httpc:set_timeout(2000)
local res, err = httpc:request_uri("https://httpbin.org/get", {
method = "GET",
ssl_verify = false
})
if not res then ngx.say("request failed: ", err); return end
ngx.say(res.status, " ", res.body)
}
}
4)ngx_brotli:压缩模块(需编译)
# 源码编译示例(OpenResty + brotli)
cd /usr/local/src
git clone https://github.com/google/ngx_brotli.git
cd ngx_brotli && git submodule update --init
# 进入 OpenResty 源码目录编译
./configure --add-module=/usr/local/src/ngx_brotli
make && make install
# 启用 brotli
brotli on;
brotli_comp_level 5;
brotli_types text/plain text/css application/javascript application/json;
四、第三方模块实践示例
1)lua-resty-openidc:OIDC 鉴权(简化版)
location /secure {
access_by_lua_block {
local openidc = require "resty.openidc"
local opts = {
discovery = "https://issuer/.well-known/openid-configuration",
client_id = "demo",
client_secret = "secret",
redirect_uri = "https://example.com/secure"
}
local res, err = openidc.authenticate(opts)
if err then ngx.status=401; ngx.say("auth failed: ", err); return ngx.exit(401) end
}
proxy_pass http://backend;
}
2)ngx_http_geoip2_module:地域分流
geoip2 /etc/nginx/GeoLite2-City.mmdb {
$geoip2_country_name country names en;
}
map $geoip2_country_name $upstream {
default backend_default;
China backend_cn;
}
upstream backend_cn { server 10.0.0.10:8080; }
upstream backend_default { server 10.0.0.11:8080; }
server {
listen 8080;
location / { proxy_pass http://$upstream; }
}
五、关键配置与命令解释
# 共享字典用于锁与缓存
lua_shared_dict lock_dict 10m;
lua_shared_dict cache_dict 100m;
# 统一超时
lua_socket_connect_timeout 1s;
lua_socket_read_timeout 2s;
lua_socket_send_timeout 2s;
# Lua 代码路径
lua_package_path "/usr/local/openresty/lualib/?.lua;;";
说明:共享字典过小会造成 evictions 增高;超时统一避免慢请求累积。
六、常见故障排查
1)库找不到
# 现象:module 'resty.http' not found
# 处理:检查 package.path
/usr/local/openresty/luajit/bin/luajit -e 'print(package.path)'
# 确认 /usr/local/openresty/lualib/?.lua 在路径中
2)连接池泄漏
# 现象:Redis 连接数激增
# 排查:确认 set_keepalive 是否执行
grep -R "set_keepalive" -n /usr/local/openresty/nginx/lua
3)共享字典溢出
# 查看 OpenResty 共享字典指标(需 stub_status 或自定义统计)
curl -s http://127.0.0.1/status | grep evictions
七、练习
1)使用 lua-resty-redis 将 /cache 接口的回源结果缓存到 Redis,设置 30 秒 TTL。
2)为 /secure 接口添加 lua-resty-session,将登录态保存在 Redis。
3)启用 lua-resty-logger-socket 将访问日志投递到本地 UDP 5514 端口,并用 nc -lu 5514 验证输出。
八、最小可运行验证
# 启动 OpenResty
sudo /usr/local/openresty/bin/openresty -p /usr/local/openresty/nginx -c conf/nginx.conf
# 验证
curl -s http://127.0.0.1:8080/cache
curl -s http://127.0.0.1:8080/http
预期:/cache 首次为 miss,再次为 hit;/http 返回 httpbin 状态与内容。