OpenResty高并发最佳实践--mysql操作,
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
-
测试
浏览器请求:http://127.0.0.1/mysql?id=1 出现以下结果,则正常测试成功
到此,Lua操作mysql完成!!!
评论暂时关闭