Concurrency Openresty中的并发模型是什么?

Concurrency Openresty中的并发模型是什么?,concurrency,nginx,lua,Concurrency,Nginx,Lua,我很难理解openresty(或nginx)的并发模型。我读了,它解释了变量的生存期,但它没有说明对它们的并发访问 很难用文字来解释,所以让我试着用代码来解释。假设我有这个Lua模块: local counter = {count = 0} function counter.incr(amount) counter.count = counter.count + (amount or 1) end return counter 然后我在openresty中使用它,如下所示: serve

我很难理解openresty(或nginx)的并发模型。我读了,它解释了变量的生存期,但它没有说明对它们的并发访问

很难用文字来解释,所以让我试着用代码来解释。假设我有这个Lua模块:

local counter = {count = 0}

function counter.incr(amount)
  counter.count = counter.count + (amount or 1)
end

return counter
然后我在openresty中使用它,如下所示:

server {
  location /incr {
    content_by_lua '
      local counter = require 'counter'
      counter.incr(1)
    '
  }
  location /decr {
    content_by_lua '
      local counter = require 'counter'
      counter.incr(-1)
    '
  }
  location /count {
    content_by_lua '
      local counter = require 'counter'
      ngx.write(counter.count)
    '
  }
}
我想了解并发模型,以便回答以下问题:

  • 如果我同时调用10次
    /incr
    ,然后调用
    /count
    ,我可以确定结果是10次吗(我假设不是,但为什么)
  • 如果我同时对
    /incr
    执行10次调用,同时又对
    /decr
    执行10次调用,我是否可以确保
    /count
    将返回0
  • 工人数量如何影响结果
  • 代码发生的阶段(即
    init_by_lua
    而不是
    content_by_lua
    )如何影响结果

nginx使用基于事件的体系结构,这意味着它使用一个带有事件循环的单线程1,当套接字准备好读取或写入时,它会处理套接字。这意味着请求实际上不是同时处理的,但是可以逐个快速处理多个请求,即使如果存在套接字/IO延迟,单个请求处理中可能会有延迟

如果我同时调用了10次/incr,然后又调用了/count,我能确定结果是10次吗(我假设不是,但为什么)

对。只要在所有
/incr
请求完成后调用
/count
,结果将是10。假设9个请求已经完成,但是第10个请求由于某种原因被发送方延迟,如果在nginx处理第10个请求之前处理了
/count
,那么结果应该是9个

如果我同时对/incr执行10次调用,同时又对/decr执行10次调用,我是否可以确保/count将返回0

是的,但不能保证这些请求的处理顺序。注意,在这种情况下,您不需要锁定您的状态或使用全局信号量或类似的东西。如果在读取状态和写回状态之间有一些I/O调用,您可能会遇到麻烦(因为在此期间可以处理不同的请求),但这不是您的示例所做的

工人数量如何影响结果

Lua实例在由同一工作进程处理的请求之间共享,因此多个工作进程不会给出相同的结果。您的所有
/incr
请求都可以转到一个worker,但是您的
/count
请求可以转到另一个worker,而另一个Lua实例(仍然)将
count
设置为0。如果需要在实例之间共享数据,则可能需要使用以下内容。有关其他选项,请参见上的一节

代码发生的阶段(即init_by_lua而不是content_by_lua)如何影响结果

init_by_lua
仅在主进程加载配置文件时执行


1我过于简单化了,因为它可以分叉多个实例来处理多核系统和其他一些情况,正如我所记得的那样。

回答太棒了,非常感谢Paul。我能问一下你是从哪里学到这些的吗?我找不到任何关于这个主题的参考资料。谢谢@kikito;不久前,作为CS课程的一部分,我读了几篇关于nginx的论文。我对他们的事件驱动体系结构非常感兴趣,与其他线程/fork服务器相比,该体系结构能够以更少的资源提供更好的结果。