为什么 resty.redis 不能与 ngx.timer 一起使用?

问题描述

我问过 here 但我想我也会在 SO 上发帖:

给定这个代码

def solution(streams):
    _max = max(streams,key=lambda x: (x[0]+x[1]))
    _max_time = _max[0] + _max[1] 
    res = [0] * _max_time
        
    for s,d,bw in streams:
        for i in range(d):
            res[s+i] += bw
    return res

我收到此错误

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)

所以线程似乎可以与 redis 一起使用,但计时器却不能。这是为什么?

解决方法

您的代码中有两个错误。

  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(检查上下文:部分)。

    您可以改用 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)