Apache到达MaxClients并locking服务器

我目前有一个运行在mpm-preforkmod_php上的带有512M真实/ 1024M可突发RAM(无交换)的OpenVZ VPS的Apache2服务器。 运行一些testing后,我发现Apache获得的最大进程大小是23M,所以我将MaxClients设置为25(23M x 25 = 575 MB,对我来说可以)。 我决定在我的服务器上运行一些负载testing,结果让我感到困惑。

我在我的台式机上使用ab ,要求wordpress博客的主页面。

当我用24个并发连接运行ab时,一切似乎都很好。 当然,CPU上升,可用RAM降低,每个请求的结果是大约2-3秒的响应时间。

但是如果我用25个并发连接(我的服务器限制)运行ab ,Apache几秒钟后就挂起了。 它开始处理请求,然后停止响应,CPU回到100%空闲, ab超时。 Apache日志说,它达到了MaxClients

当发生这种情况时,Apache保持自己locking了25个正在运行的进程(如果我检查服务器状态,它们都是“W”),并且只有在TimeOut设置进程开始死亡并且服务器再次开始响应之后(在我的情况下设置为45)。

我的问题是那个预期的行为? 为什么Apache在达到MaxClients时候就死了? 如果它与24个连接一起工作,不应该与25个工作,只是采取更多的时间来响应每个请求,其余的排队呢?

这听起来有点奇怪,任何运行ab孩子都可以通过设置与服务器MaxClients的并发连接来杀死一个web服务器。

哈! 我终于自己发现了这个问题。 这与编程比服务器pipe理更相关,但我决定在这里把答案放在这里,因为通过search谷歌,我发现我不是唯一有这样的问题(自从Apache挂起,第一个猜测是有问题与服务器)。

这个问题不是用Apache,而是用我的Wordpress。 更具体的与我的主题。 我使用的是一个名为Lightworld的主题,它支持将图像添加到博客标题。 为了做到这一点,它使用PHP的函数getimagesize()来检查图像大小。 由于这个函数打开另一个http连接到服务器来获取图像,每个来自ab请求都是从PHP内部创build另一个请求。 当我使用所有服务器可用插槽时,这些PHP请求被放入队列中,但是Apache永远不能到达它们,因为所有进程都被原始请求locking,等待一个插槽完成PHP内部请求。

基本上,PHP是我的服务器进入死锁状态,并且Apache将只在这些连接超时等待其“子”请求后才能正常工作。

在我从主题中删除了这个函数之后,现在我可以根据需要ab我的服务器中获取尽可能多的并发连接,Apache按照预期对它们进行排队。

这里发生的事情是你有25个线程能够接受连接,并且你发送了26个并发请求。 最后一个请求位于套接字队列中,具体取决于您的待办事项的大小。

第二个问题是,无论你正在运行需要2-3秒,足够长的时间来响应,25个并发连接正在放慢速度。 睡眠(1)可能会工作,但是,从MySQL执行文件locking或表locking,每个并行请求可能正在等待,直到他们达到45秒超时。

23mb对于mod_php和任何模块加载的apache进程听起来很小,所以,我怀疑你的应用程序运行时可能会看到这些apache进程需要更多内存。 你不能用MaxClients和内存那样做math…它会有点接近,但是,你永远不知道。

 www-data 1495 0.1 0.9 56288 19996 ? S 15:48 0:01 /usr/sbin/apache2 -k start www-data 1500 0.0 0.5 49684 12436 ? D 15:48 0:00 /usr/sbin/apache2 -k start 

有一台机器,56M和49M的过程。

另一台机器:

 www-data 7767 0.1 0.1 213732 14840 ? S 14:55 0:08 /usr/sbin/apache2 -k start www-data 8020 0.2 0.1 212424 13660 ? S 14:57 0:08 /usr/sbin/apache2 -k start 

另一台机器:

 www-data 28509 0.8 0.1 161720 10068 ? S 14:39 0:43 /usr/sbin/apache2 -k start www-data 28511 0.8 0.1 161932 10344 ? S 14:39 0:43 /usr/sbin/apache2 -k start 

所以,内存使用是非常依赖于任务,哪些模块加载等等。在最后两个,我相信我们已经禁用了pdo&pdo_mysql,因为该应用程序不使用它们。

真正的问题是,你在做什么,需要3秒? 在当今世界,这是一个永恒,被认为是一个“阻塞”的应用程序。 Apache通常不会死机,但会将这些线程留在积压队列中,直到它可以为它们服务或等待请求超时。 我相信你的应用程序可能会导致Apache超时。 在只包含phpinfo()的页面上试试。 看看结果是否一样。