要在Nginx中集成Lua脚本操作MySQL数据库,你需要使用OpenResty(一个集成了LuaJIT的Nginx增强版)以及相关的Lua MySQL驱动。以下是完整的实现步骤:
首先需要安装OpenResty而不是普通的Nginx:
# Ubuntu/Debian
sudo apt-get install -y software-properties-common
sudo add-apt-repository -y ppa:openresty/ppa
sudo apt-get update
sudo apt-get install -y openresty
# CentOS/RHEL
sudo yum install -y yum-utils
sudo yum-config-manager --add-repo https://openresty.org/package/centos/openresty.repo
sudo yum install -y openresty
OpenResty默认不包含MySQL驱动,需要单独安装:
# 安装LuaRocks(Lua包管理器)
wget https://luarocks.org/releases/luarocks-3.9.2.tar.gz
tar -xzvf luarocks-3.9.2.tar.gz
cd luarocks-3.9.2
./configure --prefix=/usr/local/openresty/luajit \
--with-lua=/usr/local/openresty/luajit/ \
--lua-suffix=jit \
--with-lua-include=/usr/local/openresty/luajit/include/luajit-2.1
make && sudo make install
# 安装MySQL驱动
sudo /usr/local/openresty/luajit/bin/luarocks install luasql-mysql MYSQL_INCDIR=/usr/include/mysql
编辑Nginx配置文件(通常位于/usr/local/openresty/nginx/conf/nginx.conf
):
http {
# 设置Lua包路径
lua_package_path "/usr/local/openresty/luajit/share/lua/5.1/?.lua;;";
lua_package_cpath "/usr/local/openresty/luajit/lib/lua/5.1/?.so;;";
server {
listen 80;
location /query {
# 使用content_by_lua_block处理请求
content_by_lua_block {
-- 加载MySQL驱动
local luasql = require "luasql.mysql"
-- 创建环境对象
local env = luasql.mysql()
-- 连接数据库
local conn = env:connect("database_name", "username", "password", "host", port)
if not conn then
ngx.say("Failed to connect to MySQL")
return
end
-- 执行查询
local cursor, err = conn:execute("SELECT * FROM your_table LIMIT 10")
if not cursor then
ngx.say("Query failed: ", err)
conn:close()
env:close()
return
end
-- 获取结果
ngx.say("<h1>Query Results:</h1>")
ngx.say("<table border='1'>")
-- 获取列名
local columns = {}
for i = 1, cursor:numfields() do
columns[i] = cursor:getcolname(i)
ngx.say("<th>", columns[i], "</th>")
end
-- 获取行数据
local row = cursor:fetch({}, "a")
while row do
ngx.say("<tr>")
for _, col in ipairs(columns) do
ngx.say("<td>", row[col], "</td>")
end
ngx.say("</tr>")
row = cursor:fetch(row, "a")
end
ngx.say("</table>")
-- 关闭连接
cursor:close()
conn:close()
env:close()
}
}
}
}
上述方案每次请求都新建连接,效率不高。可以使用连接池优化:
-- 在init_by_lua阶段创建连接池
init_by_lua_block {
local mysql = require "resty.mysql"
-- 创建连接池
function get_mysql_conn()
local db, err = mysql:new()
if not db then
ngx.log(ngx.ERR, "failed to instantiate mysql: ", err)
return nil, err
end
db:set_timeout(1000) -- 1秒超时
local ok, err, errno, sqlstate = db:connect{
host = "127.0.0.1",
port = 3306,
database = "test_db",
user = "test_user",
password = "test_pass",
max_packet_size = 1024 * 1024
}
if not ok then
ngx.log(ngx.ERR, "failed to connect: ", err, ": ", errno, " ", sqlstate)
return nil, err
end
return db
end
}
server {
location /query {
content_by_lua_block {
local db = get_mysql_conn()
if not db then
ngx.say("failed to connect to mysql")
return
end
local res, err, errno, sqlstate = db:query("SELECT * FROM users LIMIT 10")
if not res then
ngx.say("bad result: ", err, ": ", errno, ": ", sqlstate, ".")
return
end
ngx.say("result: ", require("cjson").encode(res))
-- 将连接放回连接池
local ok, err = db:set_keepalive(10000, 100)
if not ok then
ngx.log(ngx.ERR, "failed to set keepalive: ", err)
return
end
}
}
}
OpenResty社区提供了更高效的lua-resty-mysql
库:
sudo /usr/local/openresty/luajit/bin/luarocks install lua-resty-mysql
location /api/user {
content_by_lua_block {
local mysql = require "resty.mysql"
local db, err = mysql:new()
if not db then
ngx.say("failed to instantiate mysql: ", err)
return
end
db:set_timeout(1000) -- 1秒超时
local ok, err, errno, sqlstate = db:connect{
host = "127.0.0.1",
port = 3306,
database = "test_db",
user = "test_user",
password = "test_pass",
charset = "utf8",
max_packet_size = 1024 * 1024,
}
if not ok then
ngx.say("failed to connect: ", err, ": ", errno, " ", sqlstate)
return
end
-- 使用参数化查询防止SQL注入
local res, err, errno, sqlstate = db:query("SELECT * FROM users WHERE id = ?", {ngx.var.arg_id})
if not res then
ngx.say("bad result: ", err, ": ", errno, ": ", sqlstate, ".")
return
end
ngx.say("result: ", require("cjson").encode(res))
-- 将连接放回连接池
local ok, err = db:set_keepalive(10000, 100)
if not ok then
ngx.log(ngx.ERR, "failed to set keepalive: ", err)
return
end
}
}
lua-resty-mysql
的?
占位符)连接失败:
模块未找到:
luarocks list
确认模块已安装性能问题:
通过以上步骤,你可以在Nginx中高效地使用Lua脚本操作MySQL数据库。