ngx_lua 连接mysql

Posted by wxianfeng Sat, 16 Nov 2013 04:02:00 GMT

openresty 安装后, 默认包含 lua-resty-mysql, 我就是用的这个连接的 mysql, 很好用.

当一个 request 进来过后, 一般这么用:

local mysql = require "resty.mysql"
local db = mysql:new()
local cfg = { ... }
db:connect(cfg)
local res = db:query("select * from users")
ngx.say(json.encode(res))

但是如果我 require 的一个文件中也需要连接 mysql, 怎么办?

刚开始我这么用的:

a.lua

local Email = require("email")
local item = Email:get_item(5)

email.lua

local mysql = require("resty.mysql")
local db = mysql:new
db:connect(cfg)

function Email:get_item(id)
  local res = db:query("select * from emails where id = " .. id)
  local item = res[1]
  return item
end

一个 request 过来后, 直接报错:

> 2013/11/14 19:30:09 [error] 5290#0: *425 lua entry thread aborted: runtime
> error: attempt to yield across C-call boundary

出现这个原因是因为 require 的文件中, 不能直接有 mysql io 操作.

看下 春哥 的回复:

Hello!

2013/11/14 wxianfeng:
> 最新测试, 发现同时在两个lua文件中 db:connect(cfg) 不成功, 报下面错误:
>
> 2013/11/14 19:30:09 [error] 5290#0: *425 lua entry thread aborted: runtime
> error: attempt to yield across C-call boundary
>

这个错误是说你使用的某个 C 函数实现的 Lua 原语(比如 require 和 loadfile 之类)直接触发了 resty.mysql
的 I/O 操作(例如 connect 之类)。你应当避免让 require 和 loadfile 等操作直接触发 mysql 的 I/O
操作(比如把 mysql 相关的操作都放在你自己的 Lua 函数里,而不是放在 Lua 模块文件(.lua 文件)的顶层上)。

最后我把 email.lua 中连接 mysql 的操作, 放到一个函数中 解决.

local mysql = require("resty.mysql")
local db = mysql:new


local function connect_db()
  db:connect(cfg)
end

function Email:get_item(id)
  connect_db()
  local res = db:query("select * from emails where id = " .. id)
  local item = res[1]
  return item
end

ngx_lua log调试

Posted by wxianfeng Tue, 10 Sep 2013 02:46:00 GMT

ngx_lua 如何调试, 查看出错信息,和让修改的lua代码不重启nginx生效?
我在用 ngx_lua + lua-resty-mysql 提供json API, 每次改sql, 都需要 reload nginx , 非常麻烦. 解决办法如下:

打印输出log

可以使用 inspect.lua, 这样 print 就可以打印 lua 的 table 了, table 内的值也可以全部打印出来

local inspect = require "inspect"
local a = { retCode =  1 }
print(inspect(a))

查看输出 或者错误

查看 nginx error.log 即可以看到 print 输出, 或者出错的信息, 注意配置 error_log 指令的时候, 添加上 debug

error_log logs/error.log debug;

lua 代码修改后生效

使用 lua_code_cache off 即可, 另外注意只有使用 content_by_lua_file 才会生效.

http {
  lua_code_cache off;
}

location ~* /(\d+-.*)/api/orgunits/load_all(.*) {
   default_type 'application/json;charset=utf-8';
   content_by_lua_file /data/projects/xxx/current/lua/controller/load_data.lua;
}