ngx_http_lua_run_posted_thread
这个函数主要是为了ngx.thread.spawn的处理,ngx.thread.spawn生成新的”light thread”,这个”light thread”运行优先级比它的父协程高,会优先运行,父协程被迫暂停。”light thread”运行结束或者yield后,再由ngx_http_lua_run_posted_threads去运行父协程。
ngx.thread.spawn中创建”light thread”后, 调用ngx_http_lua_post_thread。
1 |
|
ngx_http_lua_post_thread函数将父协程放在了ctx->posted_threads指向的链表中。
1 |
|
ngx_http_lua_run_posted_threads从ctx->posted_threads指向的链表中依次取出每个元素,调用ngx_http_lua_run_thread运行。
1 |
|
ngx_http_lua_run_thread使用方式
以lua-nginx-module的Access阶段的处理为例,实际的执行工作由ngx_http_lua_access_by_chunk函数中实现。 如下面的代码,调用ngx_http_lua_run_thread后根据返回值继续处理。
1 |
|
ngx_http_lua_run_thread的返回值
函数ngx_http_lua_run_thread的返回值可分为下面几种
- NGX_OK
- NGX_AGAIN
- NGX_DONE
- NGX_ERROR: 执行出错
- 大于200: 响应的HTTP状态码
按照Nginx的处理规则,返回NGX_ERROR或大于200的HTTP状态码时,将会无条件结束当前请求的处理。 返回NGX_OK表明当前阶段处理完成,此时只需要调用ngx_http_lua_send_chain_link发送响应即可。重点关注的是NGX_AGAIN和NGX_DONE这两个。返回这两个值时都要调用ngx_http_lua_run_posted_thread来处理。
NGX_AGAIN
ngx_http_lua_run_thread什么时候会返回NGX_AGAIN?
-
- ngx.sleep或ngx.socket等导致协程的yield
-
- 调用ngx.thread导致当前请求对应的一个父协程和一个或多个”light thread”没有全部退出。 由于情况2的存在,需要调用ngx_http_lua_run_posted_thread进行处理。
NGX_DONE
在Nginx中,NGX_DONE表示对当前请求的处理已经告一段落了,但是请求还没有处理完成,之后的工作会有其他的模块进行。主要出现在三个地方
- 调用ngx_http_read_client_request_body读取请求包体时,由于从socket读取数据是异步的,会返回NGX_DONE。读取数据后对请求的处理由设置的回调函数执行
- 调用ngx_http_internal_redirect执行了内部跳转
- 创建子请求后,等待子请求完成后继续处理
在ngx_http_request_t中有一个作为引用计数的成员count。每次调用ngx_http_finalize_requet(r, NGX_DONE)时会将r的引用计数减一,减为0时才会真正结束当前请求。与此对应的模块返回NGX_DONE时都会有r->count++的操作。
在函数ngx_http_lua_access_by_chunk中当ngx_http_lua_run_thread返回NGX_DONE时(相比于返回值为NGX_AGAIN的情况)增加了一次ngx_http_finalize_request(r, NGX_DONE)的操作,就是为了将r的引用计数减一。
如果这里调用ngx_http_finalize_request(r, NGX_DONE)导致r的引用计数为0,将请求结束了,此时c->destory为true,再调用ngx_http_lua_run_posted_thread会直接返回。