Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.8k views
in Technique[技术] by (71.8m points)

nginx - why doesn't resty.redis work with the ngx.timer?

I've asked here but thought I'd post on SO as well:

given this code:

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)

I get this error:

---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

so it seems that threads work with redis but timers don't. Why is that?

question from:https://stackoverflow.com/questions/65895230/why-doesnt-resty-redis-work-with-the-ngx-timer

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

There are two errors in your code.

  1. It is not possible to pass the cosocket object between Lua handlers (emphasis added by me):

    The cosocket object created by this API function has exactly the same lifetime as the Lua handler creating it. So never pass the cosocket object to any other Lua handler (including ngx.timer callback functions) and never share the cosocket object between different Nginx requests.

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

    In your case, the reference to the cosocket object is stored in the client table (client._sock).

  2. ngx.print/ngx.say are not available in the ngx.timer.* context.

    https://github.com/openresty/lua-nginx-module#ngxsay (check the context: section).

    You can use ngx.log instead (it writes to nginx log, set error_log stderr debug; in nginx.conf to print logs to stderr).

The following code works as expected:

ngx.timer.at(2, function()
  local client = redis:new()
  client:connect('127.0.0.1' ,6379)
  ngx.log(ngx.DEBUG, #client:keys('*'))
end)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...