摘自:http://www.daileinote.com/computer/openresty/13
定时器一旦创建,就会脱离当前请求,也就是说就算当前请求结束了,定时器还是在的,它的生命周期跟创建它的 worker 进程一样。
ngx.timer.at
1 | syntax: hdl, err = ngx.timer.at(delay, callback, user_arg1, user_arg2, ...) |
创建定时器,到期时会回调 callback 函数。
delay 参数指定到期时间,单位为秒,精度0.001,代表1ms,也可以指定0,会立马过期并执行回调函数。
callback 回调函数第一个参数为 premature,接下来才是 user_arg1,user_arg2...,premature是个布尔值,代表是否是正常回调。
premature 为真的情况比如,nginx 准备关闭或者reload。
当定时器到期,回调函数以协程的方式运行,完全脱离创建该定时器的环境,对象生命周期跟创建它的worker进程一样,跟 cosockets 一样不能在原始环境和定时器回调函数里共享。
1 | location / { |
也可以循环调用,例如每5s触发一次,当然不推荐这样用,应该用 ngx.timer.every 函数。
1 | local delay = 5 |
由于定时器是在后台运行的,可能由于一些错误会耗尽系统资源,所以每个 worker 进程都会有对 未过期的定时器和正在执行的定时器数量的限制,由 lua_max_pending_timers directive,lua_max_running_timers 两个指令设置。
一个正在运行的定时器会耗掉一个连接记录,由 worker_connections 设置,所以得保证 worker_connections 够大。
在定时器回调函数里,ngx.socket.tcp、ngx.socket.udp、ngx.shared.DICT、coroutine.*、ngx.thread.*、ngx.exit、ngx.now/ngx.time、ngx.md5/ngx.sha1_bin都是允许的,但是子请求Api比如 ngx.location.capture、ngx.req.*、ngx.say/ngx.print/ngx.flush都是不允许出现的。
回调函数不允许传递 coroutine 对象,cosocket 对象。
ngx.timer.every
1 | syntax: hdl, err = ngx.timer.every(delay, callback, user_arg1, user_arg2, ...) |
类似 ngx.timer.at,只是delay不能为0,每过 delay 时间就会调用回调函数直到worker进程终止。
成功 hdl 条件为真,失败 hdl 条件为假,但是 hdl不是布尔值。
1 | server { |
这样每过5秒就会有日志记录到 logs/error.log,当 openresty reload 时,调用test回调设置 premature 为真。
ngx.timer.running_count
1 | syntax: count = ngx.timer.running_count() |
返回当前正在运行的定时器数量。
ngx.timer.pending_count
1 | syntax: count = ngx.timer.pending_count() |
返回当前没有到期的定时器数量。