我目前有一个 Apache2 服务器在 OpenVZ VPS 上运行,mpm-prefork
具有mod_php
512M 真实/1024M 可爆 RAM(无交换)。运行一些测试后,我发现 Apache 获得的最大进程大小是 23M,所以我设置MaxClients
为 25(23M x 25 = 575 MB,对我来说还可以)。我决定在我的服务器上运行一些负载测试,结果让我很困惑。
我ab
在我的台式机上使用从 wordpress 博客请求主页。
当我运行ab
24 个并发连接时,一切似乎都很好。当然,CPU 上升,可用 RAM 下降,结果是每个请求大约需要 2-3 秒的响应时间。
但是如果我运行ab
25 个并发连接(我的服务器限制),Apache 会在几秒钟后挂起。它开始处理请求,然后停止响应,CPU 回到 100% 空闲并ab
超时。Apache 日志说它达到了MaxClients
.
发生这种情况时,Apache 将自己锁定在 25 个正在运行的进程中(如果我检查服务器状态,它们都处于“W”状态)并且只有在TimeOut
设置后进程开始终止并且服务器再次开始响应(在我的情况下它已设置至 45)。
我的问题:这是预期的行为吗?为什么 Apache 在到达时就死掉了MaxClients
?如果它适用于 24 个连接,那么它不应该适用于 25 个连接,只是需要更多的时间来响应每个请求并将其余的排队?
ab
对我来说,任何运行的孩子都可以通过设置与服务器的并发连接单独杀死网络服务器,这听起来有点奇怪MaxClients
。
哈!我终于自己发现了问题。它与编程比服务器管理员更相关,但我还是决定把答案放在这里,因为通过搜索谷歌我发现我不是唯一一个遇到这种问题的人(而且由于 Apache 挂起,第一个猜测是有问题与服务器)。
问题不在于 Apache,而在于我的 Wordpress。更具体地说是我的主题。我正在使用一个名为 Lightworld 的主题,它支持将图像添加到博客标题。为此,它使用 PHP 的函数检查图像大小
getimagesize()
。由于此函数打开另一个与服务器的 http 连接以获取图像,因此每个请求ab
都在 PHP 内部创建另一个请求。由于我正在使用我所有的服务器可用插槽,这些 PHP 请求被放入队列中,但 Apache 永远无法访问它们,因为它的所有进程都被原始请求锁定,等待一个插槽来完成 PHP 内部请求。基本上,PHP 将我的服务器置于死锁状态,而 Apache 只会在这些连接超时等待它们的“子”请求后才能开始正常工作。
从我的主题中删除此功能后,现在我可以在
ab
我的服务器上使用我想要的任意数量的并发连接,并且 Apache 正在按预期对它们进行排队。这里发生的是您有 25 个线程能够接受连接,并且您正在发送 26 个并发请求。最后一个请求位于套接字队列中,具体取决于积压的大小。
第二个问题是,无论您运行什么需要 2-3 秒,都需要足够长的时间来响应 25 个并发连接正在减慢它。sleep(1) 可能有效,但是,在您从 mysql 进行文件锁定或表锁定的情况下,每个并行请求可能会在完成之前等待,直到它们达到 45 秒超时。
对于加载了 mod_php 和任何模块的 apache 进程来说,23mb 听起来很小,因此,我怀疑您可能会看到这些 apache 进程在您的应用程序运行时占用更多内存。你不能真正用 MaxClients 和这样的内存来做数学......它会有点接近,但是,你永远不会知道。
有一台机器,56M和49M进程。
另一台机器:
另一台机器:
因此,内存使用非常依赖于任务、加载了哪些模块等。在最后两个中,我相信我们已经禁用了 pdo 和 pdo_mysql ,因为该应用程序不使用它们。
真正的问题是,你在做什么需要 3 秒?在当今世界,这是永恒的,被认为是“阻塞”应用程序。Apache 通常不会死掉,但是会将这些线程留在积压队列中,直到它可以为它们提供服务或等待请求超时。我相信您的应用程序可能导致 apache 超时。在只包含 phpinfo(); 的页面上尝试 看看结果是否相同。