在Gunicorn超时中打印Django堆栈跟踪
我正在尝试调试一个Django应用程序偶尔出现的卡顿问题。目前我还没能找到具体原因,这个问题在生产环境中大约每天发生一次,而Gunicorn会重启这个进程,并显示一条信息:
[CRITICAL] WORKER TIMEOUT
有没有办法配置Django或Gunicorn,让它在重启进程时输出一个堆栈跟踪信息?
3 个回答
超时时间并不是用来限制请求的时间,而是用来检查工作进程是否还在正常运行。对于同步工作进程来说,这个超时时间就像请求的时间限制,因为同步工作进程只能处理请求,不能做其他事情。而异步工作进程在处理长时间运行的请求时,仍然会定期发送心跳信号,所以只要工作进程没有卡住或冻结,它就不会被杀掉。
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 信号时被调用。通常情况下,这个调用是在超时发生时进行的。这个可调用对象需要接受一个实例变量,用于初始化工作进程。
来源:
http://docs.gunicorn.org/en/stable/settings.html, https://github.com/benoitc/gunicorn/issues/1493, https://github.com/benoitc/gunicorn/blob/master/examples/example_config.py
这段话的意思是,当工作进程被杀掉时,它会打印出一个堆栈跟踪信息。你需要创建一个 gunicorn 配置文件,然后把下面的函数粘贴到这个文件里。
import traceback
import io
def worker_abort(worker):
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())
试着把你的Gunicorn日志设置得更详细一些,可以把它调到INFO
或者DEBUG
,这样日志里可能会有更多有用的信息。
你也可以看看Dog Slow这个工具,它可以记录慢请求的情况。链接在这里:https://pypi.python.org/pypi/dogslow。
还有一个通用的日志记录工具,叫Sentry,可以试试:https://www.getsentry.com/welcome/。
顺便问一下,服务器上那时候有没有在运行的定时任务,比如备份之类的?