Apache 性能最优化分析(4)

王朝厨房·作者佚名  2007-01-02
宽屏版  字体: |||超大  

但这种实现会引起严重的饥饿问题。由于多个子进程同时执行这个循环,它们将在select中阻塞。当任何socket上出现一个请求时,所有被阻塞的进程将复苏,并从select返回(苏醒进程的数量取决于操作系统和时间)。它们将继续执行并试图接受这个连接,但只有一个进程会成功(假设目前仍只有一个连接),其余进程将阻塞在accept中。这将把所有失败的进程锁定,使它们只为一个socket上的请求服务。它们会一直被阻塞,直到在那个socket上出现足够的请求把它们唤醒。这一饥饿问题首先在PR#467被提出。至少有两种解决它的方法。

一种方案是使用非阻塞的socket。这种情况下,accept不会阻塞子进程,它们将会立即返回。但这种方案会造成CPU时间的浪费。假设有十个在select中的空闲进程,而后到来了一个连接请求。九个进程将苏醒、试图接受连接、失败,并返回select,这些进程实际什么都没做。而且如果在这期间,其他socket上出现请求,没有哪个进程会为它服务。总而言之,这种方案不是十分有效,除非您拥有和空闲子进程数目相当的CPU--恐怕不切实际。

另一种方案被Apache采纳。这种方案串行化(serialize)对内层循环的调用。代码如下所示(改进的部分被加粗显示):

for (;;) {

accept_mutex_on ();

for (;;) {

fd_set accept_fds;

FD_ZERO (&accept_fds);

for (i = first_socket; i <= last_socket; ++i) {

FD_SET (i, &accept_fds);

}

rc = select (last_socket+1, &accept_fds, NULL, NULL, NULL);

if (rc < 1) continue;

new_connection = -1;

for (i = first_socket; i <= last_socket; ++i) {

if (FD_ISSET (i, &accept_fds)) {

new_connection = accept (i, NULL, NULL);

if (new_connection != -1) break;

}

}

if (new_connection != -1) break;

}

accept_mutex_off ();

process the new_connection;

}

accept_mutex_on和accept_mutex_off 两个函数实现了互斥量(mutual exclusion semaphore),在任意时刻只能有一个子进程拥有互斥量。多种方法可以实现互斥量。在src/conf.h(1.3版之前)或src/include/ap_config.h(1.3版及以后)可以作出以下选择。一些系统不提供任何互斥方法。在这些系统上使用多个Listen命令是不保险的。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
© 2005- 王朝网络 版权所有