OpenResty高并发最佳实践--mysql操作
文章目录
- 前言
- 准备
- 代码走着
- 测试
前言
OpenResty虽然为了提高性能更多的是使用的内存数据库(OpenResty操作redis可参考:OpenResty高并发最佳实践–Redis操作),但是特殊的时候也会存在需要操作数据库的时候,下面介绍如何通过OpenResty操作mysql
准备
不了解OpenResty的可以参考以下文章
OpenResty(Nginx+Lua)高并发最佳实践
Window下基于ZeroBrane Studio开发调试OpenResty
mysql数据库安装可参考以下文章
MySQL安装及可视化工具使用
代码走着
mysql连接池(工具类)
在OpenResty的lualib目录下创建testcode文件夹,用于放置我们的测试lua脚本,并在文件夹下创建mysql_factory.lua,如下图:
将以下代码拷贝至该文件(不需要做任何修改):local mysql = require("resty.mysql")
local mysql_pool = {}
--[[
先从连接池取连接,如果没有再建立连接.
返回:
false,出错信息.
true,数据库连接
--]]
function mysql_pool:get_connect(cfg)
if ngx.ctx[mysql_pool] then
return true, ngx.ctx[mysql_pool]
end
local client, errmsg = mysql:new()
if not client then
return false, "mysql.socket_failed: " .. (errmsg or "nil")
end
client:set_timeout(10000) --30秒
local options = {
host = cfg.db.prod.HOST,
port = cfg.db.prod.PORT,
user = cfg.db.prod.USER,
password = cfg.db.prod.PASSWORD,
database = cfg.db.prod.DATABASE
}
local result, errmsg, errno, sqlstate = client:connect(options)
if not result then
return false, "mysql.cant_connect: " .. (errmsg or "nil") .. ", errno:" .. (errno or "nil") ..
", sql_state:" .. (sqlstate or "nil")
end
local query = "SET NAMES " .. "utf8"
local result, errmsg, errno, sqlstate = client:query(query)
if not result then
return false, "mysql.query_failed: " .. (errmsg or "nil") .. ", errno:" .. (errno or "nil") ..
", sql_state:" .. (sqlstate or "nil")
end
ngx.ctx[mysql_pool] = client
-- 测试,验证连接池重复使用情况
--[[ comments by leon1509
local count, err = client:get_reused_times()
ngx.say("xxx reused times" .. count);
--]]
return true, ngx.ctx[mysql_pool]
end
--[[
把连接返回到连接池
用set_keepalive代替close() 将开启连接池特性,可以为每个nginx工作进程,指定连接最大空闲时间,和连接池最大连接数
--]]
function mysql_pool:close()
if ngx.ctx[mysql_pool] then
-- 连接池机制,不调用 close 而是 keeplive 下次会直接继续使用
-- lua_code_cache 为 on 时才有效
-- 60000 : pool_max_idle_time , 100:connections
ngx.ctx[mysql_pool]:set_keepalive(60000, 80)
-- 调用了 set_keepalive,不能直接再次调用 query,会报错
ngx.ctx[mysql_pool] = nil
end
end
--[[
查询
有结果数据集时返回结果数据集
无数据数据集时返回查询影响
返回:
false,出错信息,sqlstate结构.
true,结果集,sqlstate结构.
--]]
function mysql_pool:query(sql, flag)
local ret, client = self:get_connect(flag)
if not ret then
return false, client, nil
end
local result, errmsg, errno, sqlstate = client:query(sql)
while errmsg == "again" do
result, errmsg, errno, sqlstate = client:read_result()
end
self:close()
if not result then
errmsg = "mysql.query_failed:" .. (errno or "nil") .. (errmsg or "nil")
return false, errmsg, sqlstate
end
return true, result, sqlstate
end
return mysql_pool
配置文件
同级目录下创建config_constant.lua,用于放置redis、mysql或者其他的公共配置文件
将以下代码拷贝至该文件,具体配置数据请根据自己的mysql数据库的情况修改config = {}
config.redisConfig = {
redis_a = { -- your connection name
--ip
host = '127.0.0.1',
--端口
port = 6379,
--密码
pass = '123456789',
--超时时间,如果是测试环境debug的话,这个值可以给长一点;如果是正式环境,可以设置为200
timeout = 120000,
--redis的库
database = 0,
},
-- redis_b = {
-- -- host = '127.0.0.1',
-- -- port = 6379,
-- -- pass = '',
-- -- timeout = 200,
-- -- database = 0,
-- -- },
}
config.db = {
prod = {
HOST = "127.0.0.1",
PORT = 3306,
USER = "test",
PASSWORD = "123456789",
DATABASE = "test",
}
}
return config
测试
- 创建本地测试用户表,准备测试数据
编写测试Lua脚本
前端传递用户的ID,Lua查询出对应的用户信息返回
在testcode文件下创建mysqltest.lua并拷贝一下至该文件--平台公共的配置文件常量
local config = require "testcode.config_constant"
--mysql连接池
local mysqlUtil = require "mycode.mysql_factory"
--用于接收前端数据的对象
local args=nil
--获取前端的请求方式 并获取传递的参数
local request_method = ngx.var.request_method
--判断是get请求还是post请求并分别拿出相应的数据
if"GET" == request_method then
args = ngx.req.get_uri_args()
elseif "POST" == request_method then
ngx.req.read_body()
args = ngx.req.get_post_args()
--兼容请求使用post请求,但是传参以get方式传造成的无法获取到数据的bug
if (args == nil or args.data == null) then
args = ngx.req.get_uri_args()
end
end
--前端传递的id
local id = args.id
--组装sql语句
local sql = "select * from test_table where id = "..id
--执行sql语句
local ret, res, sqlstate = mysqlUtil:query(sql, config.db);
--判断查询结果
if(ret and res ~=nil and #res>0) then
--取出最新的值
local user = res[1]
--组装响应参数
local reVa = "id:"..user.id..";</br>name:"..user.name..";</br>age:"..user.age
--响应前端
ngx.say(reVa)
else
ngx.say("未找到用户")
end
配置OpenResty下Nginx的Lua文件关联
在nginx.con中的80配置下添加如下配置location /mysql
{
default_type text/html;
#这里的lua文件的路径为绝对路径,请根据自己安装的实际路径填写
#记得斜杠是/这个,从window中拷贝出来的是\这样,这样是有问题的,务必注意
content_by_lua_file F:/DATA/software/other/openresty-1.13.6.2-win32/lualib/testcode/mysqltest.lua;
}
- 重启OpenResty的Nginx
nginx -s reload - 测试
浏览器请求//127.0.0.1/mysql?id=1 出现以下结果,则正常测试成功
到此,Lua操作mysql完成!!!
还没有评论,来说两句吧...