nginx-lua-module文档阅读小结

数据共享

worker级别的数据共享

为了在同一个worker进程所有请求之间共享数据,可以将共享数据封装进lua模块中(用内置的require来引入模块),然后操作同一个模块来达到数据共享。之所以可以这么做是因为lua模块只被加载一次,所有的coroutines将会共享同一份拷贝(包括代码以及数据)

示例中的mydata模块只在第一个请求中被加载运行,同一个worker的后续请求将使用这个已经加载模块实例及其数据,除非向nginx master发送HUP信号来强制reload。

package.loaded

To globally share data among all the requests handled by the same Nginx worker process, encapsulate the shared data into a Lua module, use the Lua require builtin to import the module, and then manipulate the shared data in Lua. This works because required Lua modules are loaded only once and all coroutines will share the same copy of the module (both its code and data).
The mydata module in this example will only be loaded and run on the first request to the location /lua, and all subsequent requests to the same Nginx worker process will use the reloaded instance of the module as well as the same copy of the data in it, until a HUP signal is sent to the Nginx master process to force a reload. This data sharing technique is essential for high performance Lua applications based on this module.
this data sharing is on a per-worker basis and not on a per-server basis

服务器级别的数据共享

1.shared.dict
2.借助数据库

静态分析

https://github.com/openresty/openresty-devel-utils/blob/master/lua-releng

子请求

nginx子请求模拟了http调用,但并没有走网络栈,所有工作都以内部C级别高效运行

轻量级线程

轻量级线程(Light thread)是一种被ngx_lua模块调度的lua协程。

“轻量级线程”以非抢占式进行调度,换句话说,不会自动执行时间片。一个轻量级线程将会一直运行,直到

  1. (nonblocking )I/O 操作无法在一次运行中完成
  2. 调用coroutine.yield主动放弃执行
  3. 被lua error或ngx.exit,ngx.exec.ngx.redirect,ngx.req.set_uri终止

对于前两种情况,除非发生”stop-the-world”事件,否则轻量级线程将会在稍后被ngx_lua调度器恢复执行

如果当前”轻量级线程”已经终止,其父”轻量级线程”仍然存活且没有使用ngx.thread.wait对其等待,那么当”前轻量级线程”将进入”zombie”状态,可以通过coroutine.status获取状态

模拟wait all
模拟wait any

cosocket

cosocket是一套基于openresty开发的非阻塞网络基础库

如果没有主动调用close方法关闭socket对象,那么socket将在以下两种情况被释放:

  1. lua gc
  2. 当前客户端http完成处理

连接池

连接池是worker级别的,连接池的大小一旦创建后便无法修改,其大小不等于可以打开的连接最大值

连接池连接退场策略:

  1. 到达最大空闲时间的连接将自动关闭
  2. 如果连接池到达最大容量后,最近最少使用的连接将被关闭为新的连接腾让位置

tcpsock:setkeepalive使得当前cosocket对象进入”closed”状态,所以在tcpsock:setkeepalive后不必再调用tcpsock:close方法

定时器

你不能向定时器回调函数传递任何coroutine.createngx.thread.spawn的返回的线程对象以及ngx.socket.tcp,ngx.socket.udp,ngx.req.socket返回的cosocket对象,因为这些对象的生命周期与请求的上下文是绑定的,而定时器回调函数在其自己的请求上下文中运行,是与创建请求的上下文分离的,如果你试图跨创建请求的边界共享线程或cosocket,你将收到”no co ctx found”错误或”bad request”错误。
不过呢,你可以在定时器回调函数里创建这些对象。

you cannot pass any thread objects returned by coroutine.create and ngx.thread.spawn or any cosocket objects returned by ngx.socket.tcp, ngx.socket.udp, and ngx.req.socket because these objects’ lifetime is bound to the request context creating them while the timer callback is detached from the creating request’s context (by design) and runs in its own (fake) request context. If you try to share the thread or cosocket objects across the boundary of the creating request, then you will get the “no co ctx found” error (for threads) or “bad request” (for cosockets). It is fine, however, to create all these objects inside your timer callback.