OpenResy连接MySQL

最近用了纯OpenResty搭建了一个网站,后端数据库用的是MySQL。今天就来Mark一下。

话不多说,先来一个MySQL连接的简单封装:libs.mysql.lua,如下所示

local mysql = require "resty.mysql"
local configCache = ngx.shared.configCache;

local config = {
	host = configCache:get("mysql.host"),
	port = configCache:get("mysql.port"),
	database = configCache:get("mysql.database"),
	user = configCache:get("mysql.user"),
	password = configCache:get("mysql.password"),
	max_package_size = configCache:get("mysql.max_package_size"),
	charset = configCache:get("mysql.charset")
}

local _M = {}

function _M.new( self )
	local db, err = mysql:new()
	if not db then
		return nil
	end
	db:set_timeout(1000)

	local ok, err, errno, sqlstate = db:connect(config)

	if not ok then
		return nil
	end
	db.close = close
	return db
end


function close( self )
	local sock = self.sock
	if not sock then
		return nil, "not initialized"
	end
	if self.subscribed then
		return nil, "subscribed state"
	end
	return sock:setkeepalive(10000, 50)
end

return _M

首先,需要引入resty库中的mysql模块。其中db:connect(config)中的config,笔者将其放到shared Cache当中去了。抽出来了一个配置文件,如下所示:

resources.properties

{
	"projectPath" : "/Users/xuefeihu/hugege/code-sublime",

	"mysql.host" : "127.0.0.1",
	"mysql.port" : 3306,
	"mysql.database" : "xxx",
	"mysql.user" : "xxx",
	"mysql.password" : "xxx",
	"mysql.max_package_size" : 1024,
	"mysql.charset" : "utf-8"
}

在nginx.conf http模块下面新增

#初始化脚本
init_by_lua_file "/Users/xuefeihu/hugege/code-sublime/moguhu/lua/init.lua";

init.lua代码如下:

local cjson = require "cjson";
local configCache = ngx.shared.configCache;

if configCache:get('isload') then
	return
end

local resourcesFile =  io.open("/Users/xuefeihu/hugege/code-sublime/moguhu/config/resources.properties", "r");
local resourcesStr = resourcesFile:read("*a");
resourcesFile:close();


local resourcesJson = cjson.decode(resourcesStr);
ngx.log(ngx.ERR, ">>>>>>>>>>>>>>>>>>>>>>>>>>>Begin Config<<<<<<<<<<<<<<<<<<<<<<<<<<");
for k,v in pairs(resourcesJson) do
	configCache:set(k, v, 0)
	ngx.log(ngx.ERR, "key:" .. k .. ", value:" .. v);
end
ngx.log(ngx.ERR, "<<<<<<<<<<<<<<<<<<<<<<<<<<<End Config>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
configCache:set('isload', 1)

到现在为止,基础的东西已经搭建完成了。下面介绍一下使用

-- 查询详情
function _M:detail( articleId )
	articleId = ngx.quote_sql_str(articleId)

	local db = mysql:new()
	local sql = "select * from article where article_id = %s"
	sql = string.format(sql, articleId)

	db:query("SET NAMES utf8")
	local res, err, errno, sqlstate = db:query(sql)
	db:close() -- 并未真正关闭长连接,这个方法在libs.mysql.lua文件中重写了,实际调用的是setkeepalive方法
	if not res then
		ngx.say(err)
		return {}
	end

	return res[1]
end

在这里需要注意的是,demo中的db:close()方法其实并不是,resty.mysql中的close()方法。这个方法在libs.mysql.lua文件中重写了,实际调用的是setkeepalive方法。

在这里还有一点需要注意的是,在执行业务的SQL之前,执行了"SET NAMES utf8"这个SQL。这个是解决乱码问题的,其实这个是可以避免掉,方法就是修改你的 MySQL 服务器端默认的连接字符集为utf8。(由于笔者机器多次修改MySQL字符集都尚未成功,故加此代码)参见lua-resty-mysql issues: https://github.com/openresty/lua-resty-mysql/issues/20