events - 事件驱动的 I/O 如何允许多处理?

标签 events scalability multiprocessing

我知道像 select、poll、epoll 等事件驱动的 I/O 允许有人构建一个高度可扩展的 Web 服务器,但我对细节感到困惑。如果只有一个执行线程和一个进程在为服务器运行,那么当服务器为就绪客户端运行其“处理”例程时,这不是以串行方式完成以处理就绪客户端列表,因为它不能在多个内核或 CPU 上调度?此外,当这个处理发生时......服务器不会无响应吗?

我曾经认为这就是人们使用线程池来处理后端事件 I/O 的原因,但是当我最近听说并不是每个人都在他们的应用程序中使用线程池时,我感到很困惑。

最佳答案

嗯。我认为,您(原始海报)和其他答案是倒退的。

您似乎掌握了事件驱动的部分,但对事件触发后会发生的事情感到困惑。

要理解的关键是,Web 服务器通常花很少的时间“处理”请求,而花大量时间等待磁盘和网络 I/O。

当请求进来时,服务器通常需要做两件事之一。要么加载一个文件并将其发送给客户端,要么将请求传递给其他东西(经典的,一个 CGI 脚本,现在 FastCGI 由于显而易见的原因更为常见)。

在任何一种情况下,服务器的工作在计算上都是最少的,它只是客户端和磁盘或“其他东西”之间的中间人。

这就是为什么这些服务器使用所谓的 非阻塞 输入/输出。

确切的机制因操作系统而异,但关键点是读或写请求总是立即(或足够接近)返回。例如,当您尝试写入套接字时,系统要么立即接受它可以写入缓冲区的内容,要么返回诸如 EWOULDBLOCK 错误之类的内容,让您知道它现在无法接收更多数据。

一旦写入被“接受”,程序就可以记下连接的状态(例如“5000 of 10000 bytes sent”或其他内容)并继续下一个准备好采取行动的连接,回到首先在系统准备好接收更多数据之后。

这与普通阻塞套接字不同,在普通阻塞套接字中,当操作系统尝试通过网络向客户端发送数据时,大写请求可能会阻塞很长时间。

从某种意义上说,这与您可能使用线程 I/O 所做的并没有什么不同,但它大大减少了内存、上下文切换和一般“内务处理”形式的开销,并最大限度地利用了操作系统做到最好(或者应该做到):快速处理 I/O。

对于多处理器/多核系统,同样的原则适用。这种服务器在每个单独的 CPU 上仍然非常高效。您只需要一个可以 fork 自身的多个实例以利用额外的处理器。

关于events - 事件驱动的 I/O 如何允许多处理?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3231018/

相关文章:

Python:是否有一种更具可扩展性的方法来查找字符串中的所有字符串?

python - Python multiprocessing.Pool 的限制

c++ - 如何检测 QWizard 中按下的后退按钮?

asp.net - 在 ASP.NET AjaxToolkit 中捕获 Accordion 控件的 SelectedIndexChanged 事件

C#:收集 WeakReference 之前的通知?

python - scipy.misc.imread 从多线程运行是否安全/高效?

Python 多处理需要更多时间

javascript - 是否可以获取 "current"或 "last"事件的事件对象,而不将其作为处理程序中的参数接收?

algorithm - 如何处理对有限数量项目的多个请求?

performance - O(N) 是什么意思