nginx+lua的好处浅析之一

来源:互联网 发布:ui设计师求职知乎 编辑:程序博客网 时间:2024/06/05 06:30
nginx's event cycle + lua coroutine实现了一种conceptual parallelism based on events。

本质上,nginx's event cycle在Linux下的实现,就是基于epoll ET,以及EAGAIN、EWOULDBLOCK、EBUSY、EINTR等errno。这和lighttpd等实现了event-based async model的Web server是一样的,不再赘述。

主要说lua coroutine。

coroutine的执行类似于函数调用,但coroutine的return与普通函数调用不同。除了return语句和函数结束可以使一个coroutine return,yield(coroutine.yield)也可以使其return。这种return是保留状态的,可以使coroutine在将来某个时候(在nginx event cycle中使用coroutine时,实际上是某个事件发生时)继续执行,并且是在return的地方继续执行。这就使多个coroutine可以交叉执行,具备了达到conceptual parallelism的条件之一。

多个coroutine之间的交叉执行,在单CPU单核的平台上,类似于传统的multi-threading(此时的multi-threading是通过OS kernel模拟实现)。因为coroutine本质上就是函数调用,所以不同coroutine之间切换的成本非常低(couroutine switch << thread context switch < process context switch),“move back and forth so fast”。这又具备了达到conceptual parallelism的另一个条件。实测表明,在单CPU单核的平台上,coroutine的性能远好于multi-threading,在多CPU多核的平台上,coroutine与multi-threading伯仲之间,但一旦并行任务增多,multi-threading的下降曲线远陡于coroutine的。

我们采用nginx+lua model(based on lua-nginx-module),99%的情况下,不需要手写coroutine代码,因为lua-nginx-module已经为我们实现了,利用lua c api中的coroutine相关的api。在lua-nginx-module的实现中,当与一次客户端请求关联的某个事件未ready时或者某个timer未超时时,与这个请求关联的coroutine就处在suspended状态。当事件ready或timer超时时,coroutine变为running状态。

传统的multi-threading中,各个thread之间是preemptive的,实际的调度者是CPU。而coroutine是non-preemptive的,由开发者显式的决定什么时候什么情况下哪个coroutine执行,所以需要开发者来实现调度器(user codes),但在nginx+lua中,nginx为我们做了这个工作。

--demo codes in lua
local co = coroutine.create(function()
        --step 1: neccessary initialization

        --step 2: suspend itself
        local ret = coroutine.yield()

        --step 3: event ready or timer timeout
        --do what you want
end)

coroutine.resume(co)
0 0
原创粉丝点击