我正在尝试调试 Django 应用程序的罕见挂起。到目前为止,我未能隔离问题,这种情况在生产中大约每天发生一次,Gunicorn 会通过一条消息重新启动该过程:
[CRITICAL] WORKER TIMEOUT
有没有办法配置 Django 或 Gunicorn 来转储重新启动的进程的堆栈跟踪?
尝试将 Gunicorn 日志设置得更详细,也许将其设置为
INFO
或 DEBUG
可能会在日志中提供更多信息。
您还可以看看 Dog Slow,它将记录缓慢的请求。 https://pypi.python.org/pypi/dogslow.
对于一般日志记录胜利,请尝试使用 Sentry:https://www.getsentry.com/welcome/。
随机问题,当时运行的服务器上有任何 crons、备份之类的东西吗?
这将在工作线程被杀死时打印堆栈跟踪。您需要创建一个 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 有一个名为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/examples/example_config.py