Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/sqlite/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Events 事件驱动I/O如何允许多处理?_Events_Scalability_Multiprocessing - Fatal编程技术网

Events 事件驱动I/O如何允许多处理?

Events 事件驱动I/O如何允许多处理?,events,scalability,multiprocessing,Events,Scalability,Multiprocessing,我知道事件驱动的I/O(如select、poll、epoll等)允许某人构建一个高度可伸缩的web服务器,但我对细节感到困惑。如果服务器只有一个执行线程和一个进程在运行,那么当服务器为准备就绪的客户端运行其“处理”例程时,这不是以串行方式来处理准备就绪的客户端列表,因为它不能在多个核或CPU上调度吗?此外,当这种处理发生时……服务器不是没有响应吗 我曾经认为这就是人们使用线程池来处理后端事件I/O的原因,但最近我听说并不是每个人都在应用程序中使用线程池,这让我感到困惑 这里要记住的关键是,一次只

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


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

这里要记住的关键是,一次只能在CPU上执行一个线程,但I/O并不总是需要CPU。当一个线程阻塞I/O时,CPU被释放,以便另一个线程可以执行。此外,即使在一个CPU机箱上,多个线程通常也可以同时执行I/O(取决于使用的磁盘系统)。

当事件“触发”一个信号时,该信号将停止当前执行并执行信号处理程序代码

这种信号处理代码通常会产生一个新的线程/进程,然后返回(有时您会看到使用进程分叉而不是线程的实现)

底线是,如果没有多个线程,您可能会有并行执行的错觉,但实际上只是停止和启动主代码,然后处理信号处理程序

VisualBasic有类似DoEvents的功能,例如,它允许其他事件处理程序执行它们的操作。这通常用作主要工作(或循环的每次迭代)之前的一种先发制人的形式,以允许GUI在任何其他工作之间进行更新(或在您的情况下,对于开始处理客户机请求的web服务器)


另一种可能有帮助的方法是异步I/O,它将在传输完成(或刚刚处理x数量)时发出信号,所有这些都在单个执行线程中进行。尽管您必须希望您正在使用的异步I/O库支持多核处理(或底层操作系统),以便在这种情况下获得多核的好处。

其中一些智慧早于多核系统的普遍可用性。在多任务环境中,这仍然是事实。现在,除了便携式电子设备外,你接触的大多数机器都是多处理的。即使这样也可能维持不了多久

在一个纯粹的多任务系统中,操作系统所做的只是从一个作业跳到另一个作业,因为它们变得可运行(未阻塞)。事件驱动和非阻塞IO在用户空间中做同样的事情

对于某些任务,它仍然可以辅助多处理。通过减少线程产量和互斥代码,更多的处理器可以在更多的时钟周期内运行应用程序


例如,在IDE中,您不希望它不断扫描文件系统以查找外部更改。如果你在这里呆了很长时间,你可能以前就遇到过这种情况,这很烦人/没有效果。它会浪费资源,并导致全局数据模型在更新期间被锁定/无响应。设置IO事件侦听器(“目录上的watch”)可以让应用程序自由地做其他事情,比如帮助您编写代码。

其思想是,处理线程不必等待整个客户端会话完成,然后才能为另一个客户端会话提供服务。对于许多服务器应用程序,服务器的大部分时间都花在等待IO上。尽管只有一个线程处理所有请求,但增加的延迟量很小,因为服务器的大部分时间都在等待IO,在这种安排下,等待IO不会阻止服务器响应另一个请求。这种安排并不能真正帮助服务器完成大量CPU有限的处理

更具可扩展性的设置将结合异步IO和多线程,理想情况下,每个执行单元都有一个可用的工作线程,除非没有工作要做,否则不要在IO上花费任何时间睡眠。

Hmmm。我想,你(原始海报)和其他答案都是反向的

您似乎掌握了事件驱动的部分,但却被事件触发后发生的事情所困扰

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

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

在这两种情况下,服务器的工作在计算上都是最小的,它只是客户机和磁盘或“其他东西”之间的中间人

这就是为什么这些服务器使用所谓的非阻塞I/O

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

一旦写入被“接受”,程序就可以记录连接的状态(例如“发送10000字节的5000字节”或其他内容),并继续进行下一个准备好进行操作的连接,在系统准备好获取更多数据后返回第一个连接

这不同于普通的阻塞套接字,当操作系统试图通过网络向客户端发送数据时,大的写请求可能会阻塞相当长的一段时间

从某种意义上说,这