Open jinhailang opened 6 years ago
ngx_lua 中创建协程的方式主要有三种:
ngx_lua
这些函数创建的协程本质都是 lua coroutine,但由不同的角色控制(yield 或 resume),使用场景也不同,使用场景范围最大的是 ngx.timer.at 几乎每个阶段都可以使用,其他两个方法调用限制较多,具体看上面的链接。
coroutine
yield
resume
ngx.timer.at
前面已经说过,协程是不会主动出让 CPU 时间片的,除非被挂起,阻塞或者代码执行出错。因此,用户创建的协程,如果不主动退出,比如代码进入了死循环,就无法切换执行其他的协程,而且,因为父协程执行的优先级比子协程低,所有请求处理都在同一个主协程内,如果子协程执行时间太长,就会导致 worker 进程请求处理缓慢,甚至卡死,影响整个 OpenResty 处理效率。
另一个问题,当在请求子协程(rewrite, access, content 阶段)内调用 ngx.thread.spawn 或 coroutine.create 创建协程,可能会阻塞当前请求,因为请求子协程是用户创建协程的父协程,必须要所有子协程结束,才能退出,执行下个阶段。ngx.timer.at 创建的协程是与请求协程无关的,可以认为它的父线程是 worker 主协程,所以,当它阻塞时,并不会影响请求处理。
ngx.thread.spawn
coroutine.create
因为协程之间数据是异步的,所以,在协程内使用外部数据要格外小心,最好直接使用参数调用,避免出现非预期的数据变化。
ngx.timer.at 是延迟执行,可以递归实现定时执行的效果,delay 延迟参数不能设置的太小,否则会拖慢当前 worker 的请求处理速度。当需要定时执行的时候,可以直接使用 ngx.timer.every,更简洁,而且 delay 不能为 0。
delay
ngx.timer.every
0
总之,最关键的是与其他语言(例如 Golang)不同, lua 虚拟机没有实现协程管理功能,完全由用户自己控制,使用不当会严重影响程序性能!
ngx_lua
中创建协程的方式主要有三种:ngx_lua
模块控制,最推荐这些函数创建的协程本质都是 lua
coroutine
,但由不同的角色控制(yield
或resume
),使用场景也不同,使用场景范围最大的是ngx.timer.at
几乎每个阶段都可以使用,其他两个方法调用限制较多,具体看上面的链接。前面已经说过,协程是不会主动出让 CPU 时间片的,除非被挂起,阻塞或者代码执行出错。因此,用户创建的协程,如果不主动退出,比如代码进入了死循环,就无法切换执行其他的协程,而且,因为父协程执行的优先级比子协程低,所有请求处理都在同一个主协程内,如果子协程执行时间太长,就会导致 worker 进程请求处理缓慢,甚至卡死,影响整个 OpenResty 处理效率。
另一个问题,当在请求子协程(rewrite, access, content 阶段)内调用
ngx.thread.spawn
或coroutine.create
创建协程,可能会阻塞当前请求,因为请求子协程是用户创建协程的父协程,必须要所有子协程结束,才能退出,执行下个阶段。ngx.timer.at
创建的协程是与请求协程无关的,可以认为它的父线程是 worker 主协程,所以,当它阻塞时,并不会影响请求处理。因为协程之间数据是异步的,所以,在协程内使用外部数据要格外小心,最好直接使用参数调用,避免出现非预期的数据变化。
ngx.timer.at
是延迟执行,可以递归实现定时执行的效果,delay
延迟参数不能设置的太小,否则会拖慢当前 worker 的请求处理速度。当需要定时执行的时候,可以直接使用ngx.timer.every
,更简洁,而且delay
不能为0
。总之,最关键的是与其他语言(例如 Golang)不同, lua 虚拟机没有实现协程管理功能,完全由用户自己控制,使用不当会严重影响程序性能!