我们的 Apache+Django 服务器存在工作线程卡住的问题。这是一个 mpm 工作线程模型,一段时间后,每个为几十个工作线程提供服务的进程的所有工作线程都会被冻结:
# 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 的所有工作进程都处于“工作”状态。当前,PID 为 822 和 5284。并且,这些进程不处理任何功能请求。此外,只能使用信号 9 ( kill -9
)来终止它们
该选项WSGIDaemonProcess cpu-time-limit=120/120
对我们没有帮助,原因有二:只有 WSGI 3.0 及更高版本才具有该选项,而且,这些进程不消耗 CPU,因此它们的 CPU 时间很低。
我们的服务器速度有些慢。速度不是特别慢,但可能会快一些(有时会挂起请求),我怀疑这个问题与此有关。无论如何,它不应该这样。
这是一台 Ubuntu 10.04 LTS 服务器,带有 Apache 2.2.14 和 libapache2-mod-wsgi 2.8-2ubuntu1。网站服务如下:
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。
答案1
首先,由于各种原因,您的 MPM 设置有点问题。建议您观看我在 PyCon 上的演讲:
至于您的服务器挂起,您可能使用了第三方扩展模块,而该模块不适合从子解释器使用。您需要强制您的应用程序在主解释器中运行。请参阅:
要找出进程挂起的位置,还可以参见获取堆栈跟踪的方法,如下所述:
- http://code.google.com/p/modwsgi/wiki/DebuggingTechniques#Debugging_Crashes_With_GDB
- http://code.google.com/p/modwsgi/wiki/DebuggingTechniques#Extracting_Python_Stack_Traces
如果正如预期的那样出现死锁并且不想尝试使用主解释器,则可能需要使用 gdb 来获取卡住位置的堆栈跟踪。
如果问题在于您的代码在调用外部服务时被阻止,则 Python 堆栈跟踪方法将起作用。您也可以通过使用 lsof 或 ofiles 查看打开的文件描述符来了解这一点。
答案2
我修好了它前段时间,我们将网站转换为使用守护进程模式,而不是嵌入模式,并在其前面放置一个 nginx 代理,来处理所有静态文件服务。