Gunicorn工作超时错误

我已经设置了gunicorn与3个工人30个工人连接和使用eventlet工人类。它在Nginx后面设置。每请求几次,我就会在日志里看到这个。

[ERROR] gunicorn.error: WORKER TIMEOUT (pid:23475)
None
[INFO] gunicorn.error: Booting worker with pid: 23514

为什么会这样?我怎样才能知道哪里出了问题?

谢谢

294111 次浏览

--log-level debug运行Gunicorn。

它应该会给你一个应用程序堆栈跟踪。

会是这样吗? http://docs.gunicorn.org/en/latest/settings.html#timeout < / p >

其他的可能是你的回复时间太长或者被困在等待中。

你需要使用另一个worker类型类,比如gevent龙卷风,更多解释见此: 第一个解释:

如果您预计应用程序代码在请求处理期间可能需要暂停较长时间,您可能还需要安装Eventlet或Gevent

第二点:

默认的同步工作线程假定您的应用程序在CPU和网络带宽方面受到资源限制。通常这意味着您的应用程序不应该执行任何花费未定义时间的操作。例如,对互联网的请求就符合这个标准。在某些时候,外部网络会出现故障,客户端会堆积在您的服务器上。

我们在使用Django+nginx+gunicorn时也遇到了同样的问题。从Gunicorn文档中,我们配置了优雅的超时,几乎没有什么不同。

经过一些测试,我们找到了解决方案,要配置的参数是:timeout(并且不是优雅超时)。它走得像时钟一样快。

所以,做:

1)打开gunicorn配置文件

2)将TIMEOUT设置为您需要的任何值-以秒为单位

NUM_WORKERS=3
TIMEOUT=120


exec gunicorn ${DJANGO_WSGI_MODULE}:application \
--name $NAME \
--workers $NUM_WORKERS \
--timeout $TIMEOUT \
--log-level=debug \
--bind=127.0.0.1:9000 \
--pid=$PIDFILE

我有非常类似的问题,我也尝试使用“运行服务器”,看看我是否能找到任何东西,但我所拥有的只是一个消息Killed

所以我认为这可能是资源问题,我继续给实例更多的RAM,它工作了。

在谷歌云上 只需将--timeout 90添加到app.yaml

的入口点
entrypoint: gunicorn -b :$PORT main:app --timeout 90

WORKER TIMEOUT意味着你的应用程序不能在规定的时间内响应请求。你可以使用Gunicorn超时设置来设置。一些应用程序需要比另一个应用程序更多的时间来响应。

另一个可能影响它的东西是选择工作人员类型

默认的同步工作线程假定您的应用程序在CPU和网络带宽方面受到资源限制。通常这意味着您的应用程序不应该执行任何花费未定义时间的操作。一个花费不确定时间的例子是对互联网的请求。在某些时候,外部网络会出现故障,客户端会堆积在您的服务器上。因此,从这个意义上讲,任何向api发出外发请求的web应用程序都将受益于异步工作线程。

当我遇到与您相同的问题时(我试图使用Docker Swarm部署我的应用程序),我尝试增加超时并使用另一种类型的工人类。但都失败了。

然后我突然意识到我限制了我的资源过低在我的撰写文件中的服务。在我的例子中,这就是减慢应用程序的原因

deploy:
replicas: 5
resources:
limits:
cpus: "0.1"
memory: 50M
restart_policy:
condition: on-failure

所以我建议你先检查一下是什么减慢了你的应用程序

我在Docker中也遇到了同样的问题。

在Docker中,我保持训练过的LightGBM模型+ Flask服务请求。作为HTTP服务器,我使用gunicorn 19.9.0。当我在我的Mac笔记本电脑上本地运行我的代码时,一切都很完美,但当我在Docker中运行应用程序时,我的POST JSON请求冻结了一段时间,然后gunicorn worker一直失败,出现[CRITICAL] WORKER TIMEOUT异常。

我尝试了大量不同的方法,但唯一解决我的问题的是添加worker_class=gthread

以下是我的完整配置:

import multiprocessing


workers = multiprocessing.cpu_count() * 2 + 1
accesslog = "-" # STDOUT
access_log_format = '%(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(q)s" "%(D)s"'
bind = "0.0.0.0:5000"
keepalive = 120
timeout = 120
worker_class = "gthread"
threads = 3

如果使用GCP,则必须为每个实例类型设置worker。

链接到GCP最佳实践https://cloud.google.com/appengine/docs/standard/python3/runtime

对我来说,解决方案是将--timeout 90添加到我的入口点,但它不起作用,因为我定义了两个入口点,一个在app.yaml中,另一个在我的Dockerfile中。我删除了未使用的入口点,并在另一个入口点中添加了--timeout 90

超时是这个问题的一个关键参数。

然而,它不适合我。

当我设置workers=1时,我发现没有gunicorn超时错误。

当我看虽然我的代码,我发现一些Socket连接(Socket。发送,Socket.recv)在服务器init中。

套接字。Recv将阻塞我的代码,这就是为什么它总是超时时,工人>1

希望能给那些对我有意见的人一些建议

这个端点是否花费了太多时间?

也许你使用的flask没有异步支持,所以每个请求都会阻塞调用。要创建异步支持而不让make变得困难,可以添加gevent工作对象。

使用gevent,一个新的调用将产生一个新的线程,你的应用程序将能够接收更多的请求

pip install gevent
gunicon .... --worker-class gevent

这招对我很管用:

gunicorn app:app -b :8080 --timeout 120 --workers=3 --threads=3 --worker-connections=1000

如果你有eventlet,添加:

--worker-class=eventlet

如果你有gevent,添加:

--worker-class=gevent

对我来说,这是因为我忘记在数据库服务器上为我的Django设置防火墙规则。

弗兰克的回答给我指明了正确的方向。我有一个数字海洋液滴访问管理数字海洋Postgresql数据库。我所需要做的就是将我的液滴添加到数据库的“可信来源”中。

(在DO控制台点击数据库,然后点击设置。编辑Trusted Sources,选择液滴名称(在可编辑区域点击,会提示)。

关于在Azure应用服务(Linux应用)上运行Flask Apps的Microsoft Azure官方文档声明超时时间为600

gunicorn --bind=0.0.0.0 --timeout 600 application:app

https://learn.microsoft.com/en-us/azure/app-service/configure-language-python#flask-app

如果你已经更改了django项目的名称,你也应该去

cd /etc/systemd/system/

然后

sudo nano gunicorn.service

然后验证在绑定行的末尾,应用程序名称已更改为新的应用程序名称

检查你的工人没有被健康检查杀死。长请求可能会阻塞健康检查请求,worker会被平台杀死,因为平台认为worker没有响应。

例如,如果您有一个25秒长的请求,并且活动检查被配置为每10秒命中同一服务中的不同端点,1秒超时,并重试3次,这就给出了10+1*3 ~ 13秒,您可以看到它会触发一些时间,但并不总是如此。

如果是这种情况,解决方案是重新配置您的活动检查(或您的平台使用的任何健康检查机制),以便它可以等待您的典型请求完成。或者允许更多的线程——这样可以确保健康检查不会阻塞足够长的时间来触发worker kill。

你可以看到,增加更多的工人可能有助于(或隐藏)这个问题。

对我来说,最简单的方法是在你的app.py存在的文件夹中创建一个新的config.py文件,并在其中放入超时和所有你想要的特殊配置:

timeout = 999

然后在指向这个配置文件的同时运行服务器

gunicorn -c config.py --bind 0.0.0.0:5000 wsgi:app

注意,要使这条语句工作,还需要将wsgi.py放在具有以下内容的同一目录中

from myproject import app


if __name__ == "__main__":
app.run()

干杯!