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

Bor*_*ltz 15 events scalability multiprocessing

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

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

Nic*_*ght 9

嗯.你(原始海报)和其他答案,我认为,这是倒退.

你似乎掌握了事件驱动的部分,但是在事件发生后会发生什么事情.

了解事情的关键是,Web服务器通常花短的时间"处理"的要求,和很多的时间等待磁盘和网络I/O.

当请求进入时,服务器通常需要做两件事之一.加载文件并将其发送到客户端,或将请求传递给其他东西(通常,CGI脚本,现在FastCGI更常见,原因很明显).

在任何一种情况下,服务器的工作都是计算最小的,它只是客户端和磁盘之间的中间人或"别的东西".

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

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

一旦写入被"接受",程序就可以记录连接的状态(例如"5000个10000字节发送"或其他东西),然后继续下一个准备采取行动的连接,返回到在系统准备好接收更多数据之后.

这与普通的阻塞套接字不同,当一个OS尝试通过网络向客户端发送数据时,大写请求可能会阻塞很长一段时间.

从某种意义上说,这与您使用线程I/O所做的事情并没有什么不同,但它在内存,上下文切换和一般"内务管理"方面的开销大大减少,并且最大限度地利用了什么操作系统做得最好(或者无论如何):快速处理I/O.

对于多处理器/多核系统,适用相同的原则.这种类型的服务器在每个CPU上仍然非常高效.你只需要一个可以分叉自身的多个实例来利用额外的处理器.