分析
假设有下面的配置
location / {
content_by_lua 'ngx.sleep(100);'
}
````
当你的终端有一个请求: `curl -i 127.0.0.1:8080/` 过来后,会发生下面的调用链路关系:
![4029f43e46c097a1a19e93efe6b2c241.png](https://i-blog.csdnimg.cn/blog_migrate/9d32b08ffe2d9a1cc308a25d4ed0f3d8.jpeg)
请求达到nginx
后,nginx
的核心就发起一个路由定位,找到location
后,就生成一个请求,然后这个请求中,发现了content_by_lua
的指令,就加载lua
的虚机,执行里面的lua
脚本。
lua
脚本中的代码,又是通过c扩展(ngx_http_lua_sleep.c
)来实现的,所以lua虚机进入c代码,给nginx
增加一个timer
(含回调函数ngx_http_lua_sleep_handler
),然后告诉lua可以挂起了。
nginx
在等待事件到了之后,会发出一个timer_event
的事件,找到对应的回调函数(ngx_http_lua_sleep_handler
),开始调用ngx_http_lua_sleep_handler
,ngx_http_lua_sleep_handler
就将对应的lua虚机唤醒,代码控制全转移到lua虚机上,lua虚机继续执行lua代码,代码结束后,回到c代码,执行完c代码,控制权回到nginx
验证
准备
- 将nginx配置为如下
daemon off;
master_process off;
worker_processes 1;
events {
worker_connections 1024;
}
error_log logs/error.log debug;
http {
server {
listen 8080;
location / {
content_by_lua '
-- unit is second
ngx.sleep(2)
ngx.log(ngx.INFO, "log for hello world")
ngx.say("hello world")
';
}
}
}
- 开启nginx的调试日志
开启这个日志的前提是nginx
使用--with-debug
编译。
按照文件https://github.com/openresty/lua-nginx-module/blob/master/src/ngx_http_lua_sleep.c
中的代码描述,按照前面的分析,会依次打印日志
lua ready to sleep for ...
lua sleep timer expired ...
lua run thread ...
log for hello word
调试
那我们调试的结果是:
一个终端执行:
mkdir logs
openresty -p `pwd` -c conf/nginx.conf
另一个终端请求:
curl -i 127.0.0.1:8080
得到如下日志:
![29daa54e65f6e50ceb04903a8e74373a.png](https://i-blog.csdnimg.cn/blog_migrate/af1f1a9b8618a584c50c6d2efe24b6f9.jpeg)
从图中,我们可以看到,还是符合分析预期的。
小结
请求进来后,nginx的先构建自己内部的上下文,然后调用到lua虚拟机,lua虚机挂起后, 还需要nginx来唤醒,然后再从原先挂起的地方开始执行。