Apache、mod_wsgi、Django-奇怪的 500 错误

Apache、mod_wsgi、Django-奇怪的 500 错误

我有一个 Django 网站,它大多数时候运行良好,内存使用情况稳定,如果没有一些奇怪的问题,我就不用担心,这些问题直到昨天才偶尔出现,并导致网站昨晚整个晚上都处于瘫痪状态。

配置:

  • 德比安·兰尼
  • Apache 2.2 预分叉
  • mod_wsgi 的新功能
  • Python 2.5.2
  • Django 1.2.5

我得到的回溯:

[error] mod_wsgi (pid=7390): Exception occurred within sys.exitfunc().
[error] Traceback (most recent call last):
[error]   File "/usr/lib/python2.5/atexit.py", line 24, in _run_exitfuncs
[error]     func(*targs, **kargs)
[error]   File "/usr/lib/python2.5/logging/__init__.py", line 1354, in shutdown
[error]     h.flush()
[error]   File "/usr/lib/python2.5/logging/__init__.py", line 731, in flush
[error]     self.stream.flush()
[error] IOError: sys.stdout access restricted by mod_wsgi

上面的错误经常在我重启 Apache 或者 touch .wsgi 文件时产生,所以我并不太在意。下面这些比较有意思:

[error] [client ..] mod_wsgi (pid=8184): Exception occurred processing WSGI script '.../django.wsgi'.
[error] [client ..] Traceback (most recent call last):
[error] [client ..] File ".../django/core/handlers/wsgi.py", line 248, in __call__
[error] [client ..]   response = self.get_response(request)
[error] [client ..] File ".../django/core/handlers/base.py", line 140, in get_response
[error] [client ..]   receivers = signals.got_request_exception.send(sender=self.__class__, request=request)
[error] [client ..] File "...django/dispatch/dispatcher.py", line 172, in send
[error] [client ..]   response = receiver(signal=self, sender=sender, **named)
[error] [client ..] File "...django/db/transaction.py", line 299, in _commit_on_success
[error] [client ..]   res = func(*args, **kw)
[error] [client ..] File ".../apps/utils/middleware.py", line 28, in exception_handler
[error] [client ..]   'url': request.get_full_path()
[error] [client ..] File "/usr/lib/python2.5/logging/__init__.py", line 1015, in error
[error] [client ..]   apply(self._log, (ERROR, msg, args), kwargs)
[error] [client ..] File "/usr/lib/python2.5/logging/__init__.py", line 1101, in _log
[error] [client ..]   self.handle(record)
[error] [client ..] File "/usr/lib/python2.5/logging/__init__.py", line 1111, in handle
[error] [client ..]   self.callHandlers(record)
[error] [client ..] File "/usr/lib/python2.5/logging/__init__.py", line 1148, in callHandlers
[error] [client ..]   hdlr.handle(record)
[error] [client ..] File "/usr/lib/python2.5/logging/__init__.py", line 655, in handle
[error] [client ..]   self.emit(record)
[error] [client ..] File "../apps/py26_logging/handlers.py", line 394, in emit
[error] [client ..]   self.stream.flush()
[error] [client ..] ValueError: I/O operation on closed file

一句话解释:因为我使用 logrotate 进行日志轮换,所以我将 logs.WatchedFileHandler 从 Python 2.6“反向移植”到项目中,放置在 中apps/py26_logging/handlers.py,但我的猜测是,不是 WatchedFileHandler 导致了这个问题,它只受到更普遍的问题的影响 - 因为 95% 的时间它都运行良好。

无论如何,Apache 重启可以立即解决问题(当然直到下一次)。

我用于服务器监控的 ServerDensity 显示稳定的内存使用情况(直线),任何时候都有至少 500mb 的可用内存,进程数量也很稳定,而且当我的应用程序出现问题时,统计数据通常不会出现任何异常。

我尝试使用 ApacheBench 重现该问题,但除非我同时使用 100 个请求,否则我无法使任何单个请求失败:

并发级别:100 完成请求:10000 失败请求:1(连接:0、接收:0、长度:1、异常:0) 写入错误:0 非 2xx 响应:1

我不用说,这远远超出了通常的负载,并且 ServerDensity 统计数据大幅上升。

你们中有人看到这里熟悉的模式了吗?

答案1

我只能对IOError: sys.stdout access restricted by mod_wsgi错误进行评论。您的 Django-App 中的某些内容写入了sys.stdoutmod_wsgi 限制的内容。通常,sys.stdoutWSGI 应用程序中不会发生任何输出。您可以WSGIRestrictStdout Off在全局 Apache 配置(而不是 vhost)中使用作为创可贴。要获得永久而干净的解决方案,请删除任何print或任何写入的内容sys.stdout。有关更多详细信息,请查看mod_wsgi 文档

相关内容