【问题标题】:FastCgi crashes -- Want to catch all exceptions but how?FastCgi 崩溃——想要捕获所有异常但如何捕获?
【发布时间】:2009-05-09 18:00:25
【问题描述】:

我有一个使用 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 而不必担心无限循环吗?我应该为有问题的异常调用请求返回一个错误 HttpRequest 吗?我什至不知道该怎么做。

我一直在查看 django/core/servers/fastcgi.py 和 django/core/handlers/wsgi.py 和 django/http/init.py

我无法在理解 Flup 方面取得进展。

有我可以学习的想法或经验吗?

谢谢!

【问题讨论】:

    标签: python django fastcgi wsgi flup


    【解决方案1】:

    这可能是一个 Flup bug。当基于 Flup 的服务器的客户端连接在 Flup 完成发送数据之前关闭时,它会引发 socket.error: (32, 'Broken pipe') 异常。

    试图通过 runfastcgi 周围的 try catch 来捕获异常是行不通的。仅仅因为异常是由线程引发的。

    好的,我将解释为什么将您自己的代码包装在 try catch 中不起作用。如果您仔细查看异常回溯,您会发现跟踪中的第一条语句不是 runfastcgi。那是因为异常发生在不同的线程中。如果要捕获异常,则需要将跟踪列出的任何语句包装在 try/catch 中,如下所示:

    # in file /usr/lib/python2.4/site-packages/Trac-0.12dev_r7715-py2.4.egg/trac/web/_fcgi.py", line 654, in run
    try:
        self.process_input()
    except socket.error:
        # ignore or print an error
        pass
    

    关键是,您可以通过修改 Flup 的代码来捕获错误。但我看不出这有什么好处。特别是因为这个异常似乎是无害的,而且已经有补丁了。

    【讨论】:

    • 好的。发生错误是因为客户端在flup完成之前关闭了连接。然而,当我只是去我网站的主页时,就会发生这种情况。看起来好像服务器已经崩溃,或者至少是 fastcgi,但这些是我看到的唯一错误。有什么建议如何调试吗?
    • 您是否尝试过应用错误票中提到的补丁?它可能会解决您的问题。错误是否导致请求失败?还是只是显示在日志中而没有明显的副作用?
    • 我正试图弄清楚破裂的管道是原因还是症状。嗯...我想我可以应用补丁看看。不过,更多地了解如何调试或了解情况将是我的偏好。不想追逐冒险的红鲱鱼。
    • 好的,我在答案中添加了更多细节,希望这会让事情更清楚
    【解决方案2】:

    断管通常不是确定性的。如果对管道或套接字的写操作由于另一端已关闭连接而失败,您会得到一个Broken pipe。所以如果你的 FastCGI 得到一个Broken pipe,这意味着网络服务器已经过早地关闭连接。在某些情况下,这不是问题,可以静默忽略。

    作为一个快速破解,尝试使用Broken pipe 捕获并忽略socket.error。您可能需要在更多地方添加except: 子句。

    【讨论】:

    • “还有很多地方” 感谢您的提示,但恐怕我还在学习。在哪里?我宁愿不修补 django 或 Flup。我很高兴修改 dispatch.fcgi 和我自己的 django 应用程序。
    猜你喜欢
    • 2017-07-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多