init_worker_by_lua 中设置死循环reload后导致worker进程无法退出

301 views
Skip to first unread message

L.D

unread,
Mar 23, 2016, 3:11:05 AM3/23/16
to openresty
在init_worker_by_lua模块中,保持与后端服务websocket连接,来获取后端推送信息,代码大概如下:
local handler
handler = function(premature) 
    if premature then 
        return 
    end
    local client = require "resty.websocket.client"
    local wb, err = client:new()
   --接收服务端响应
    while true do
        local data, typ, err = wb:recv_frame()
        if client.fatal then
            ngx.log(ngx.ERR, 'failed to receive frame: ',err,typ)
            --try to reconnect
        end
        if not data then
            local bytes, err = wb:send_ping()
            if not bytes then
                ngx.log(ngx.ERR, 'failed to send ping: ', err)
            end
        elseif typ == 'close' then
            --try to reconnet
        elseif typ == 'ping' then
            local bytes, err = wb:send_pong()
            if not bytes then
                ngx.log(ngx.ERR, 'failed to send pong: ', err)
            end
        elseif typ == 'pong' then
            ngx.log(ngx.INFO, 'client ponged')
        elseif typ == 'text' then
            ngx.log(ngx.INFO,'data:[text]:',data)
            -- data 处理
        end
    end 
end

local ok, err = new_timer(2, handler) 
if not ok then 
    log(ngx.ERR, "failed to create handler timer: ", err) 
    return 
end

在使用nginx -s reload后,发现worker状态处于is shutting down状态,原因应该是由于死循环导致无法退出,这种情况下我该如何正常退出,或者在循环中
该如何捕捉reload信号

L.D

unread,
Mar 23, 2016, 4:15:53 AM3/23/16
to openresty


还有我这种设置,会影响nginx worker的正常转发吗?

L.D

unread,
Mar 23, 2016, 5:13:53 AM3/23/16
to openresty
现在在循环中使用  
if ngx.worker.exiting() then
      ngx.exit()
end
可以成功退出了,扔疑惑会影响nginx worker的性能吗

L.D

unread,
Mar 24, 2016, 12:43:53 AM3/24/16
to openresty

在压测的过程中又出现问题了:
nginx启动了16个worker进程,压测时,对nginx进行reload后,执行
ps -ef|grep "worker process"|wc

发现worker进程会多出来好几个,打log发现未进入ngx.worker.exiting()流程中
但在未有流量的时候,reload都是运行ok的,求大神支招


在 2016年3月23日星期三 UTC+8下午5:13:53,L.D写道:

瞿秋丰

unread,
Mar 24, 2016, 5:27:18 AM3/24/16
to openresty
ping pong 的时候没反应就可以exit了吧

在 2016年3月24日星期四 UTC+8下午12:43:53,L.D写道:

L.D

unread,
Mar 24, 2016, 5:38:08 AM3/24/16
to openresty
hi,我是nginx reload,nginx worker作为客户端维持ping pong,没反应是怎么去判断?


在 2016年3月24日星期四 UTC+8下午5:27:18,瞿秋丰写道:

Guanglin Lv

unread,
Mar 24, 2016, 11:22:46 PM3/24/16
to openresty

首先,确认下reload时多出来的worker是什么状态,是你循环的那个worker么?

另外,如果reload时worker上存在业务,比如长连接等,该worker不会理解退出的,会pending一段时间,直到业务结束。


在 2016年3月24日星期四 UTC+8下午12:43:53,L.D写道:

L.D

unread,
Mar 25, 2016, 3:09:06 AM3/25/16
to openresty
我用resty.lock只让一个worker进入这个循环,我是在mac上测试的,每次reload都会多出6个worker进程,且多出来的进程状态正常,看了下进程id,
应该是那几个进程未退出导致的,在另外一台linux服务器上测试,reload却发现是正常的。目前已经没有头绪了。

在 2016年3月25日星期五 UTC+8上午11:22:46,Guanglin Lv写道:

Yichun Zhang (agentzh)

unread,
Mar 27, 2016, 3:10:26 PM3/27/16
to openresty
Hello!

2016-03-23 0:11 GMT-07:00 L.D:
> 在init_worker_by_lua模块中,保持与后端服务websocket连接,来获取后端推送信息,代码大概如下:
> --接收服务端响应
> while true do
> local data, typ, err = wb:recv_frame()
[...]
> 在使用nginx -s reload后,发现worker状态处于is shutting
> down状态,原因应该是由于死循环导致无法退出,这种情况下我该如何正常退出,或者在循环中
> 该如何捕捉reload信号

你应该在循环内部自己检查 ngx.worker.exiting 的返回值:

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

当返回真值时,应当自己主动退出循环。否则 nginx 会认为你还有未完成的工作要做,从而一直等待。这被称为“graceful shutdown”特性。

Regards,
-agentzh

rr Feng

unread,
Mar 28, 2016, 2:16:29 AM3/28/16
to openresty
我有一个类似的问题
在 init_by_worker 中使用 timer 启动一个 lua-resty-http 请求,这个请求是被阻塞的(etcd 的 watch api),直到返回数据。
如果不设置 socket timeout 的话,那么这个请求就会一直处于等待状态,然后 reload 的时候 worker process 就不会退出。
有没有办法从外部终止 timer 启动的 thread?(即使在 init_by_worker 中拿到了 ngx.worker.exiting 的状态也没有办法进入到 lua-resty-http 中干掉它啊……)

所以现在临时将 timeout 设置为 1min,如果 reload 的话,worker process 最多会多存活 1min 再退出,感觉不是很优雅。

L.D

unread,
Mar 28, 2016, 3:05:43 AM3/28/16
to openresty
使用了春哥的那种方式是可以退出的,你用lua-resty-http不设置socket timeout 的话,会有个默认值的吧,可以把socket time设置小点。

在 2016年3月28日星期一 UTC+8下午2:16:29,rr Feng写道:

L.D

unread,
Mar 28, 2016, 3:11:16 AM3/28/16
to openresty
谢谢春哥,这种方式是可以实现的。还有点对于init_by_worker不明白的是,
我是直接在timer里使用循环,还是再起个thread里面循环,这两张方式对worker处理性能有影响吗?

在 2016年3月28日星期一 UTC+8上午3:10:26,agentzh写道:

Yichun Zhang (agentzh)

unread,
Mar 31, 2016, 2:31:47 PM3/31/16
to openresty
Hello!

2016-03-28 0:11 GMT-07:00 L.D:
> 谢谢春哥,这种方式是可以实现的。还有点对于init_by_worker不明白的是,
> 我是直接在timer里使用循环,还是再起个thread里面循环,这两张方式对worker处理性能有影响吗?
>

多一个(light) thread,多一点开销,虽然不大。这是显然的。应当只在需要额外并发的时候创建新的轻线程。

Regards,
-agentzh
Reply all
Reply to author
Forward
0 new messages