6

我正在尝试调试 Django 应用程序的罕见挂起。到目前为止,我未能找出问题所在,它在生产中大约每天发生一次,Gunicorn 通过一条消息重新启动该过程:

[CRITICAL] WORKER TIMEOUT

有没有办法配置 Django 或 Gunicorn 来转储重新启动的进程的堆栈跟踪?

4

3 回答 3

6

尝试将您的 Gunicorn 日志设置为更详细,也许将其设置为INFO或者DEBUG可能会在日志中提供更多信息。

您还可以查看 Dog Slow,它将记录慢速请求。https://pypi.python.org/pypi/dogslow

对于一般的日志记录,请尝试使用 Sentry:https ://www.getsentry.com/welcome/ 。

随机问题,当时在服务器上运行的任何 crons、备份之类的东西?

于 2013-03-17T00:23:18.260 回答
3

这将在工作人员被杀死时为其打印堆栈跟踪。您需要创建一个gunicorn 配置文件,并将以下函数粘贴到其中。

def worker_abort(worker):
    import traceback, io
    debug_info = io.StringIO()
    debug_info.write("Traceback at time of timeout:\n")
    traceback.print_stack(file=debug_info)
    worker.log.critical(debug_info.getvalue())

(我只在 Python 3 上对此进行了测试。如果您使用 Python 2,则需要更改ioStringIO。请参阅Python3 中的 StringIO

于 2019-06-19T16:00:40.683 回答
1

timeout 并不意味着请求超时。这意味着对工人的活动性检查。对于同步工作人员,这起到了请求超时的作用,因为工作人员除了处理请求之外不能做任何事情。异步工作人员即使在处理长时间运行的请求时也会心跳,因此除非工作人员阻塞/冻结它不会被杀死。

Gunicorn 有一个名为 worker_abort 的函数(参见下面的 gunicorn 文档)。

def worker_abort(worker):
    worker.log.info("worker received abort signal")
    import threading, sys, traceback
    id2name = dict([(th.ident, th.name) for th in threading.enumerate()])
    code = []
    for threadId, stack in sys._current_frames().items():
        code.append("\n# Thread: %s(%d)" % (id2name.get(threadId,""), threadId))
        stack = traceback.extract_stack(stack)
        for filename, lineno, name, line in stack:
            code.append('File: "%s", line %d, in %s' % (filename, lineno, name))
            if line:
                code.append("  %s" % (line.strip()))
    worker.log.debug("\n".join(code))

当工作人员收到 SIGABRT 信号时调用。此调用通常在超时时发生。可调用对象需要为已初始化的 Worker 接受一个实例变量。

资料来源:

http://docs.gunicorn.org/en/stable/settings.html,https://github.com/benoitc/gunicorn/issues/1493,https://github.com/benoitc/gunicorn/blob/master/ _ _ _ _示例/example_config.py

于 2017-08-17T16:48:31.803 回答