FastCgi 崩溃——想要捕获所有异常,但如何捕获?
我有一个使用 fastcgi 在 apache 上运行的 django 应用程序(使用 Flup 的 WSGIServer)。
这通过dispatch.fcgi 进行设置,连接如下:
#!/usr/bin/python
import sys, os
sys.path.insert(0, os.path.realpath('/usr/local/django_src/django'))
PROJECT_PATH=os.environ['PROJECT_PATH']
sys.path.insert(0, PROJECT_PATH)
os.chdir(PROJECT_PATH)
os.environ['DJANGO_SETTINGS_MODULE'] = "settings"
from django.core.servers.fastcgi import runfastcgi
runfastcgi(method="threaded",daemonize='false',)
runfastcgi 负责完成这项工作,最终在 WSGIHandler 上运行 WSGIServer。
有时会发生导致 fastcgi 崩溃的异常。
编辑:我不知道什么错误导致 fastcgi 崩溃,或者 fastcgi 是否崩溃。 我只知道有时网站会宕机——持续宕机——直到我重新启动 apache。 error.log 中出现的唯一错误是损坏的管道和不完整的标头,如下所列。
不完整的标题:
注意:我已用“...”替换了敏感信息或混乱 破损
[Sat May 09 ...] [error] [client ...] (104)Connection reset by peer: FastCGI: comm with server ".../dispatch.fcgi" aborted: read failed
[Sat May 09 ...] [error] [client ...] FastCGI: incomplete headers (0 bytes) received from server ".../dispatch.fcgi"
[Sat May 09 ...] [error] [client ...] (32)Broken pipe: FastCGI: comm with server ".../dispatch.fcgi" aborted: write failed,
的管道:
注意:这恰好是针对 trac 站点而不是 django 应用程序,但它看起来是一样的。
Unhandled exception in thread started by <bound method Connection.run of <trac.web._fcgi.Connection object at 0xb53d7c0c>>
Traceback (most recent call last):
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 654, in run
self.process_input()
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 690, in process_input
self._do_params(rec)
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 789, in _do_params
self._start_request(req)
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 773, in _start_request
req.run()
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 582, in run
self._flush()
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 589, in _flush
self.stdout.close()
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 348, in close
self._conn.writeRecord(rec)
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 705, in writeRecord
rec.write(self._sock)
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 542, in write
self._sendall(sock, header)
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 520, in _sendall
sent = sock.send(data)
socket.error: (32, 'Broken pipe')
我查看了 /var/log/apache2/error.log,但似乎找不到崩溃的原因。 我有时会遇到内存交换问题,但我认为这是不同的。 (请原谅我的无知。我愿意学习如何更好地实现和调试服务器管理内容。)
我想用 try/ except 包装 runfastcgi 。 处理随机异常的最佳方法是什么(直到我找出实际原因)?
我相信 WSGIServer 可以处理很多请求。 如果我捕获异常,我可以重新调用 runfastcgi 而不必担心无限循环吗? 我应该为有问题的异常调用请求返回 Error HttpRequest 吗? 我什至不知道该怎么做。
我一直在浏览 django/core/servers/fastcgi.py 和 django/core/handlers/wsgi.py 和 django/http/init.py
我一直无法取得进展理解事情的一面。
有我可以借鉴的想法或经验吗?
谢谢!
I have a django app running on apache with fastcgi (uses Flup's WSGIServer).
This gets setup via dispatch.fcgi, concatenated below:
#!/usr/bin/python
import sys, os
sys.path.insert(0, os.path.realpath('/usr/local/django_src/django'))
PROJECT_PATH=os.environ['PROJECT_PATH']
sys.path.insert(0, PROJECT_PATH)
os.chdir(PROJECT_PATH)
os.environ['DJANGO_SETTINGS_MODULE'] = "settings"
from django.core.servers.fastcgi import runfastcgi
runfastcgi(method="threaded",daemonize='false',)
The runfastcgi is the one that does the work, eventually running a WSGIServer on a WSGIHandler.
Sometimes an exception happens which crashes fastcgi.
EDIT: I don't know what error crashes fastcgi, or whether fastcgi even crashes. I just know that sometimes the site goes down--consistently down--until I reboot apache. THe only errors that appear in the error.log are the broken pipe and incomplete headers ones, listed below.
Incomplete headers:
note: I've replaced sensitive information or clutter with "..."
[Sat May 09 ...] [error] [client ...] (104)Connection reset by peer: FastCGI: comm with server ".../dispatch.fcgi" aborted: read failed
[Sat May 09 ...] [error] [client ...] FastCGI: incomplete headers (0 bytes) received from server ".../dispatch.fcgi"
[Sat May 09 ...] [error] [client ...] (32)Broken pipe: FastCGI: comm with server ".../dispatch.fcgi" aborted: write failed,
Broken pipe:
note: this happens to be for a trac site not a django app, but it looks the same.
Unhandled exception in thread started by <bound method Connection.run of <trac.web._fcgi.Connection object at 0xb53d7c0c>>
Traceback (most recent call last):
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 654, in run
self.process_input()
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 690, in process_input
self._do_params(rec)
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 789, in _do_params
self._start_request(req)
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 773, in _start_request
req.run()
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 582, in run
self._flush()
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 589, in _flush
self.stdout.close()
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 348, in close
self._conn.writeRecord(rec)
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 705, in writeRecord
rec.write(self._sock)
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 542, in write
self._sendall(sock, header)
File "/usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 520, in _sendall
sent = sock.send(data)
socket.error: (32, 'Broken pipe')
I've looked through /var/log/apache2/error.log, but I can't seem to find the cause of the crashing. I sometimes have memory swapping problems, but I think this is different. (Please excuse my ignorance. I am willing to learn how to implement and debug server admin stuff better.)
I'd like to wrap the the runfastcgi with a try/except. What is the best way to handle random exceptions (until I figure out the actual cause(s))?
I believe the WSGIServer handles many requests. If I catch an exception, can I re-call runfastcgi without fear of an infinite loop? Should I return an Error HttpRequest for the offending, exception-calling request? I'm not even sure how to do that.
I've been looking through django/core/servers/fastcgi.py and django/core/handlers/wsgi.py and django/http/init.py
I haven't been able to make progress understanding flup's side of things.
Have ideas or experiences I might learn from?
Thanks!
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这可能是 Flup bug。 当基于 flup 的服务器的客户端连接在 flup 完成发送数据之前关闭时,它会引发 socket.error: (32, 'Broken pipeline') 异常。
尝试通过 runfastcgi 周围的 try catch 来捕获异常是行不通的。 很简单,因为异常是由线程引发的。
好的,我将解释为什么将您自己的代码包装在 try catch 中不起作用。 如果仔细查看异常回溯,您会发现跟踪中的第一个语句不是 runfastcgi。 那是因为异常发生在不同的线程中。 如果你想捕获异常,你需要将跟踪列出的任何语句包装在 try/catch 中,如下所示:
重点是,你可以通过修改 Flup 的代码来捕获错误。 但我看不出这有什么好处。 特别是因为这个异常似乎是无害的,并且已经有一个补丁。
This is probably a Flup bug. When a flup-based server's client connection is closed before flup is done sending data, it raises a socket.error: (32, 'Broken pipe') exception.
Trying to catch the exception by a try catch around runfastcgi will not work. Simply because the exception is raised by a thread.
OK, I'll explain why the wrapping your own code in a try catch won't work. If you look closely at the exception traceback you'll see that the first statement in the trace is not runfastcgi. That's because the exception is happening in a different thread. If you want to catch the exception you need to wrap any of the statements listed by the trace in a try/catch like this:
The point is, you can catch the error by modifing Flup's code. But I don't see any benefit from this. Especial because this exception seems to be harmless and there already is a patch for it.
管道破裂通常不是确定性的。 如果管道或套接字上的写入操作因另一端关闭了连接而失败,则会出现“管道损坏”的情况。 因此,如果您的 FastCGI 出现管道损坏,则意味着网络服务器过早关闭了连接。 在某些情况下这不是问题,可以默默地忽略它。
作为一个快速技巧,尝试捕获并忽略带有
Broken pipeline
的socket.error
。 您可能需要在更多地方添加except:
子句。Broken pipe usually doesn't come deterministically. You get a Broken pipe if a write operation on a pipe or socket fails because the other end has closed the connection. So if your FastCGI gets a Broken pipe, it means that the webserver has closed to connection too early. In some cases this is not an problem, it can be ignored silently.
As a quick hack, try to catch and ignore the
socket.error
withBroken pipe
. You may have to add anexcept:
clause to many more places.