最近,由于内存问题,我已经从Apache预叉(PHP模块)更改为mpm-worker (PHP)。我正在运行一个相当大的PHP应用程序,每个预分叉进程需要20-30米。
总的来说,服务器运行稳定且快速。但是,有时,某些用户在几分钟内无法使用该页面。
工作假设1(=粗略的想法)是,其中一个进程(通常是2个,有时高达5或6个)挂起,分配给该进程的每个客户端(例如,50%的客户端)都会收到错误消息。
工作假设2是MaxRequestsPerProcess负责。在500个调用之后,进程试图关闭,mod_fcgid不会优雅地终止,而当进程等待终止时,更多的客户端被分配给(并被进程拒绝)。但我不能想象阿帕奇会这么蠢。
我的问题是:错误日志中除了一些
[warn] mod_fcgid: process ???? graceful kill fail, sending SIGKILL我想不出什么办法去追踪这个问题了。它似乎偶尔出现,我还没有设法激怒它。服务器性能(CPU/RAM)不应成为问题,因为总体负载在最近几周的较低范围内。
谢谢你的暗示。对我的假设有什么评论(这无助于我找到解决方案,但我试图禁用MaxRequestsPerProcess,但还不知道它是否有帮助)?我将非常感谢一些如何跟踪这个问题的想法。
<Directory /var/www/html>
...
# PHP FCGI
<FilesMatch \.phpA3gt;
SetHandler fcgid-script
</FilesMatch>
Options +ExecCGI
</Directory>
<IfModule mod_fcgid.c>
FcgidWrapper /var/www/php-fcgi-starter .php
# Allow request up to 33 MB
FcgidMaxRequestLen 34603008
FcgidIOTimeout 300
FcgidBusyTimeout 3600
# Set 1200 (>1000) for PHP_FCGI_MAX_REQUESTS to avoid problems
FcgidMaxRequestsPerProcess 1000
</IfModule><IfModule mod_fcgid.c>
AddHandler fcgid-script .fcgi
FcgidConnectTimeout 20
FcgidBusyTimeout 7200
DefaultMinClassProcessCount 0
IdleTimeout 600
IdleScanInterval 60
MaxProcessCount 20
MaxRequestsPerProcess 500
PHP_Fix_Pathinfo_Enable 1
</IfModule>注意:超时设置为2小时,因为很少情况下,应用程序可能需要一些时间来运行(例如,执行数据库优化的夜间任务)。
#!/bin/sh
PHP_FCGI_MAX_REQUESTS=1200
export PHP_FCGI_MAX_REQUESTS
export PHPRC="/etc/php5/cgi"
exec /usr/bin/php5-cgi
#PHP_FCGI_CHILDREN=10
#export PHP_FCGI_CHILDREN发布于 2013-08-14 13:29:47
我认为每个进程20到30 as是相当小的。这一切都是相对的,但例如,大多数CMS应用程序至少需要100‘s。此外,您的最大上传大小将受到最大进程大小的限制,如果这是重要的。
当您的服务器不可用时,可能php工作进程都很忙,但是这只是一个直接原因。服务器的速度减慢了,至少在一段时间内,php进程无法跟上传入的请求。什么在减慢您的服务器是很难判断,但‘优雅的杀死失败’让我认为,被杀死的进程很可能在磁盘上等待。
这事发生的时候你登录了吗?系统是否有反应?
在顶部,查看流程状态,并查找等待IO的“D”状态。有很多这样的吗?顶部汇总中的“wa”是进程在IO上等待的总时间。(上面写着百分比,但这很可能是一个处理器时间的百分比)。像iotop、atop和vmstat这样的工具对于查看哪些进程被磁盘绑定,以及磁盘在多大程度上限制了您的整体性能也很有用。
当工作进程无法接受新请求时,您对发生什么情况的理解是不正确的。新的请求将不会分配给它。
杀死工人前的1000个请求很高。我建议把它放在10到50之间。
发布于 2013-08-14 13:50:15
我认为你的建议是正确的。mc0e的建议是非常可靠的,所以我主要是在增加它。
您正在看到的这些日志消息表明,单个进程正被锁定在预叉MPM下,这给您提供了比worker更好的进程隔离。我以前在生产环境中见过这种情况,这意味着您有一些错误的代码。
在你对每个孩子的最高要求和你的挂起过程之间,这就为记忆膨胀设置了舞台。文档特别涵盖了非零值有助于防止内存泄漏。这一事实,但是如果您将该值设置得太高,就会失去好处。让您的进程挂在上面,只会进一步加重整个内存占用。
这给你留下了两个即时的外快:
MaxRequestsPerChild所暗示的,降低mc0e的幅度是很大的。这有助于防止单个进程存活足够长的时间来积累重要的记忆leaks...but,就像他说的那样,200-3000万可能不是什么大问题。lsof可能会提供一个提示,这取决于代码所做的事情(即文件句柄泄漏,达到最大文件句柄上限可能与进程死锁有关),但否则您将看到代码调试。https://serverfault.com/questions/527007
复制相似问题