Openresty 中的并发模型是什么? [英] What is the concurrency model in Openresty?

查看:27
本文介绍了Openresty 中的并发模型是什么?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我很难理解 openresty(或 nginx)的并发模型.我阅读了 Lua 变量范围,它解释了变量的生命周期,但它没有说明并发访问给他们.

I am having a hard time trying to wrap my head around openresty's (or nginx's) concurrency model. I read the Lua variable scope, which explains the lifetime of variables, but it says nothing about concurrent access to them.

文字很难解释,所以我试着用代码来解释.想象一下,我有这个 Lua 模块:

It is difficult to explain in words, so let me try to explain with code. Imagine that I have this Lua module:

local counter = {count = 0}

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

return counter

然后我像这样在 openresty 中使用它:

And then I use it in openresty like this:

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)
    '
  }
}

我想了解并发模型,以便回答以下问题:

I want to understand the concurrency model so I can answer these questions:

  • 如果我对 /incr 进行 10 次并发调用,然后我调用 /count,我能否确定结果是 10(我假设不会,但为什么)?
  • 如果我对 /incr 进行 10 次并发调用,同时对 /decr 进行另外 10 次并发调用,我能确定 /count 会返回 0?
  • 工人数量如何影响结果?
  • 代码发生的阶段(即init_by_lua 而不是content_by_lua)对结果有何影响?
  • If I do 10 concurrent calls to /incr, and later on I call /count, can I be sure that the result will be 10 (I assume not, but why)?
  • If I do 10 concurrent calls to /incr and at the same time I do another 10 to /decr, can I be sure that /count will return 0?
  • How does the number of workers influence the results?
  • How does the phase in which the code happens (i.e. init_by_lua instead of content_by_lua) influence the results?

推荐答案

nginx 使用基于事件的架构,这意味着它使用单线程1 和一个事件循环来处理套接字变为准备好阅读或写作.这意味着请求并不是真正同时处理,而是可以一个一个快速处理多个请求,即使如果有任何套接字/IO延迟,单个请求处理可能会出现延迟.

nginx is using event-based architecture, which means it's using a single thread1 with an event loop that handles sockets when they become ready for reading or writing. This means that requests are not really handled at the same time, but several requests can be quickly handled one-by-one, even though there may be delays in individual request processing if there are any socket/IO delays.

如果我对/incr 进行 10 次并发调用,然后又调用/count,我能确定结果是 10(我认为不是,但为什么)?

If I do 10 concurrent calls to /incr, and later on I call /count, can I be sure that the result will be 10 (I assume not, but why)?

是的.只要/count所有/incr请求完成后调用,结果就是10个.想象一下9个请求都完成了,但是第 10 个请求由于某种原因被发送方延迟了,如果 /count 在第 10 个请求被 nginx 处理之前处理,你应该得到 9 作为结果.

Yes. As long as /count is called after all /incr requests are finished, the result will be 10. Imagine that 9 requests have been finished, but the 10th request was for some reason delayed by the sender, and if /count was processed before the 10th request was handled by nginx, you should get 9 as the result.

如果我同时对/incr 进行 10 次调用,同时对/decr 进行 10 次并发调用,我能确定/count 会返回 0 吗?

If I do 10 concurrent calls to /incr and at the same time I do another 10 to /decr, can I be sure that /count will return 0?

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

Yes, but the order in which these requests will be handled is not guaranteed. Note that in this case you don't need to lock your state or use global semaphores or anything like that. You may run into trouble if you have some I/O calls between reading state and writing it back (as a different request can be handled during that time), but this is not what your example does.

工人数量如何影响结果?

How does the number of workers influence the results?

Lua 实例在由同一个工作进程处理的请求之间共享,因此多个工作进程不会给你相同的结果.您所有的 /incr 请求都可以发送到一个 worker,但是您的 /count 请求可以发送到另一个 worker,使用不同的 Lua 实例(仍然)具有 count 设置为 0.如果你需要在实例之间共享数据,你可能需要使用类似 lua_shared_dict 的东西.另请参阅数据共享部分以了解其他选项.

Lua instances are shared between requests handled by the same worker process, so multiple workers are not going to give you the same result. All your /incr requests can go to one worker, but your /count request can go to a different worker, with a different Lua instance that (still) has count set to 0. If you need to share data between instances, you probably need to use something like lua_shared_dict. See also the section on data sharing for other options.

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

How does the phase in which the code happens (i.e. init_by_lua instead of content_by_lua) influence the results?

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

init_by_lua is only executed when the master process loads the config file.

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

1 I'm oversimplifying as it can fork multiple instances to handle multi-core systems and some other cases as well as far as I remember.

这篇关于Openresty 中的并发模型是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆