nginx:它的多线程但使用多个进程?

Posted

技术标签:

【中文标题】nginx:它的多线程但使用多个进程?【英文标题】:nginx : Its Multithreaded but uses multiple processes? 【发布时间】:2011-06-13 11:28:56 【问题描述】:

我想了解是什么让 nginx 如此之快,我有几个问题。

据我了解,Apache 要么生成一个新进程来服务每个请求,要么生成一个新线程来服务每个请求。由于每个新线程共享虚拟地址空间,因此如果有大量并发请求进入,内存使用量会不断攀升。

Nginx 通过只有一个监听进程(Master)、一个执行线程和 2 或 3 个(数量可配置)工作进程来解决这个问题。这个主进程/线程正在运行一个事件循环。有效地等待任何传入的请求。当一个请求进来时,它会将该请求提供给其中一个工作进程。

如果我的上述理解不正确,请纠正我

如果以上是正确的,那么我有几个问题:

    工作进程不会产生多个线程并遇到与 apache 相同的问题吗?

    或者 nginx 速度很快,因为它基于事件的架构在其底层使用了非阻塞 IO。也许工作进程会产生非阻塞 IO 的线程,是这样吗?

    “确切地说”是“基于事件的架构”,有人可以真正简化它,让像我这样的人理解。它只是与非阻塞 io 或其他东西有关吗?

我得到了c10k 的引用,我正在尝试通过它,但我不认为它与基于事件的拱门有关。似乎更多的是非阻塞 IO。

【问题讨论】:

非阻塞 IO 需要基于事件的架构。 仅供参考 - 以防你有兴趣深入挖掘 - 我已经将答案与其他材料 + 视频一起写在这里:planetunknown.blogspot.com/2011/02/… Apache 并不是因为它创建的线程太多而慢,而是因为它们之间的上下文切换,这比执行指令消耗的 CPU 时间片要多。 【参考方案1】:

Apache 使用多个线程为每个请求提供它自己的执行线程。这是在使用同步 I/O 时避免阻塞所必需的。

Nginx 只使用异步 I/O,这使得阻塞不再是问题。 nginx 使用多进程的唯一原因,是为了充分利用多核、多 CPU 和超线程系统。即使有 SMP 支持,内核也无法在多个 CPU 上调度单个执行线程。每个逻辑 CPU 至少需要一个进程或线程。

所以区别在于,nginx只需要足够的工作进程来获得 SMP 的全部好处,而 Apache 的架构需要创建一个新线程(每个线程都有自己的堆栈大约〜8MB)每个请求。显然,在高并发下,Apache 将使用更多的内存,并因维护大量线程而承受更大的开销。

【讨论】:

@spockwang 实际上,他们使用一名工人作为核心。 在大多数情况下推荐的 NGINX 配置——每个 CPU 内核运行一个工作进程——可以最有效地利用硬件资源。来自NGINX docs 显然他们已经引入了多线程读取以减少主线程上的“阻塞”,但我认为答案是正确的。nginx.com/blog/thread-pools-boost-performance-9x【参考方案2】:

从概念的角度来看,这并不是很复杂。我会尽量清楚,但我必须做一些简化。

基于事件的服务器(如nginx 和lighttpd)使用事件监控系统的包装器。例如。 lighttpd 使用libevent 抽象出更高级的高速事件监控系统(另见libev)。

服务器为每个连接使用一个简单的状态机来跟踪它拥有的所有非阻塞连接(写入和读取)。当有新数据可用或何时可以写入更多数据时,事件监控系统会通知服务器进程。如果您了解套接字编程,这就像类固醇上的select()。然后,服务器进程在可能的情况下使用一些高级功能(如sendfile())简单地发送请求的文件,或者使用套接字将请求转换为 CGI 进程进行通信(该套接字将像其他网络连接一样被事件监控系统监控。)

This 链接作为很多关于 nginx 内部的重要信息,以防万一。希望对你有帮助。

【讨论】:

感谢 Ass3mbler。我认为这有助于理解它。 @PlanetUnknow 我很高兴它有帮助。如果您需要更多信息,请问我,我已经多次修改 lighttpd 的来源。如果可以,你能接受我的回答吗?谢谢! 感谢 Ass3mbler。我认为这有助于理解它。所以主进程正在监听传入的流量,而工作进程正在运行事件循环(注册事件并在事件发生时响应)。总而言之,对吗?【参考方案3】:

Apache 不会为每个请求生成一个新线程。它维护一个线程缓存或一组预先分叉的进程,它将请求外包给这些进程。并发请求的数量受子/线程数量的限制,是的,但是 apache 不会为每个请求生成一个新线程/子,这会非常慢(即使有线程,每个请求的创建和拆除也会太慢)

Nginx 使用主从模式。主进程处理加载配置和创建/销毁/维护工人。与 apache 一样,它开始于许多已经运行的预分叉进程,每个进程都是一个工作进程(其中一个是“主”进程)。每个工作进程共享一组监听套接字。每个工作进程都接受连接并处理它们,但每个工作进程可以同时处理数千个连接,这与 apache 不同,每个工作进程只能处理 1 个连接。

nginx 实现这一点的方式是通过“多路复用”。它不使用 libevent,它使用了一个专门为 nginx 设计的自定义事件循环,并随着 nginx 软件的开发而发展。多路复用的工作原理是使用循环通过程序块逐块“递增”对一个数据/新连接/每个连接/每个循环迭代的对象进行操作。它全部基于 Epoll()、kqueue() 和 select() 等后端。您应该阅读的内容

【讨论】:

以上是关于nginx:它的多线程但使用多个进程?的主要内容,如果未能解决你的问题,请参考以下文章

java中的多线程

Java中的多线程技术全面详解

Java中的多线程技术全面详解

python下的多线程与多进程

python多线程作用

python的多线程