我们的Apache+Django服务器存在worker卡死的问题。这是一个 mpm worker 模型,一段时间后,为几十个工作线程提供服务的每个进程都冻结了它的所有 worker:
# apache2ctl status
Apache Server Status for localhost
Server Version: Apache/2.2.14 (Ubuntu) mod_ssl/2.2.14 OpenSSL/0.9.8k mod_wsgi/
2.8 Python/2.6.5
Server Built: Mar 8 2013 16:46:38
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
Current Time: Friday, 05-Apr-2013 15:56:17 CEST
Restart Time: Thursday, 04-Apr-2013 11:23:23 CEST
Parent Server Generation: 11
Server uptime: 1 day 4 hours 32 minutes 53 seconds
Total accesses: 244313 - Total Traffic: 4.7 GB
CPU Usage: u181.45 s33.97 cu.62 cs0 - .21% CPU load
2.38 requests/sec - 47.9 kB/second - 20.2 kB/request
108 requests currently being processed, 42 idle workers
_K__K______KK_____W_________W________K_K__________..............
WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW..............
WWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWWW..............
................................................................
................................................................
................................................................
Scoreboard Key:
"_" Waiting for Connection, "S" Starting up, "R" Reading Request,
"W" Sending Reply, "K" Keepalive (read), "D" DNS Lookup,
"C" Closing connection, "L" Logging, "G" Gracefully finishing,
"I" Idle cleanup of worker, "." Open slot with no current process
执行时apache2ctl fullstatus
,您可以看到恰好有两个 PID 使它们的所有 worker 都处于“工作”状态。当前,PID 822 和 5284。而且,这些进程不处理任何功能请求。此外,他们只能用信号 9 ( kill -9
)
该选项WSGIDaemonProcess cpu-time-limit=120/120
不会帮助我们,原因有两个:只有 WSGI 3.0 版和更高版本有它,另外,进程不消耗 CPU,因此它们的 CPU 时间很低。
我们的服务器运行缓慢。它不是超级慢,但它可以更快(有时它挂在请求上),我怀疑这个问题是相关的。无论如何,它不应该是这样的。
它是带有 Apache 2.2.14 和 libapache2-mod-wsgi 2.8-2ubuntu1 的 Ubuntu 10.04 LTS 服务器。网站的服务方式如下:
WSGIScriptAlias / /srv/http/bla/passenger_wsgi.py
这是工人配置:
<IfModule mpm_worker_module>
StartServers 2
MinSpareThreads 25
MaxSpareThreads 75
ThreadLimit 64
ThreadsPerChild 50
MaxClients 200
ServerLimit 6
MaxRequestsPerChild 1000
</IfModule>
知道这是什么以及如何解决它吗?或者,至少如何在这些进程上设置一些自动终止?ulimit 很难,因为它们不会大量消耗 CPU。
一开始由于各种原因,您的 MPM 设置有点损坏。建议您观看我在 PyCon 上的演讲:
至于您的服务器挂起,您可能正在使用第三方扩展模块,从子解释器使用它是不安全的。您需要强制您的应用程序在主解释器中运行。看:
要找出进程挂起的位置,请参阅获取堆栈跟踪的方法,如中所述:
如果它是预期的死锁并且不想只尝试使用主解释器,则可能需要使用 gdb 来获取卡住位置的堆栈跟踪。
如果问题是您的代码阻塞了对外部服务的调用,则 Python 堆栈跟踪方法将起作用。您也可以通过使用 lsof 或 ofiles 查看打开的文件描述符来了解这一点。
我前段时间通过将站点转换为使用守护程序模式而不是嵌入式模式来修复它,并在它前面放置一个 nginx 代理,它处理所有静态文件服务。