为什么 resty.redis 不能与 ngx.timer 一起工作?

我在这里询问过,但我也想在 Stack Overflow 上发布:

给定这段代码:

local redis = require('resty.redis')

local client = redis:new()
client:connect(host,port)
ngx.thread.spawn(function()
  ngx.say(ngx.time(),' ',#client:keys('*'))
end)
ngx.timer.at(2,function()
  ngx.say(ngx.time(),' ',#client:keys('*'))
end)

我得到了这个错误:

---urhcdhw2pqoz---
1611628086 5
2021/01/26 10:28:08 [error] 4902#24159: *4 lua entry thread aborted: runtime error: ...local/Cellar/openresty/1.19.3.1_1/lualib/resty/redis.lua:349: bad request
stack traceback:
coroutine 0:
    [C]: in function 'send'
    ...local/Cellar/openresty/1.19.3.1_1/lualib/resty/redis.lua:349: in function 'keys'
    ./src/main.lua:20: in function <./src/main.lua:19>, context: ngx.timer

看起来线程可以与 redis 一起工作,但定时器不行。为什么呢?

点赞
用户9783845
用户9783845

你的代码中有两个错误。

  1. 不能在 Lua 处理程序之间传递 cosocket 对象(在 加粗的部分):

    由此 API 函数创建的 cosocket 对象的生命周期与创建它的 Lua 处理程序完全相同。因此永远不要将 cosocket 对象传递给任何其他 Lua 处理程序(包括 ngx.timer 回调函数),也永远不要在不同的 Nginx 请求之间共享 cosocket 对象。

    https://github.com/openresty/lua-nginx-module#ngxsockettcp

    在你的代码中,对 cosocket 对象的引用存储在 client 表中(client._sock)。

  2. ngx.print/ ngx.sayngx.timer.* 上下文中不可用。

    https://github.com/openresty/lua-nginx-module#ngxsay(查看 context: 部分)。

    你可以使用 ngx.log 代替(它将写入 Nginx 日志,将 error_log stderr debug; 设置在 nginx.conf 中以将日志打印到 stderr)。

以下代码按预期工作:

ngx.timer.at(2, function()
  local client = redis:new()
  client:connect('127.0.0.1' ,6379)
  ngx.log(ngx.DEBUG, #client:keys('*'))
end)
2021-01-26 18:06:59