<p>gunicorn 关键工人超时</p>

创建于 2017-01-21  ·  18评论  ·  资料来源: benoitc/gunicorn

我正在使用以下设置运行 gunicorn:
gunicorn --worker-class gevent --timeout 30 --graceful-timeout 20 --max-requests-jitter 2000 --max-requests 1500 -w 50 --log-level DEBUG --capture-output --bind 0.0.0.0:5000 run:app并且我在除了 3 个工人之外的所有人中看到[CRITICAL] WORKER TIMEOUT 。 一段时间后,gunicorn 不能再产生工人,或者至少产生它们的速度非常慢。 这导致它不会使服务器可达,任何请求都不可达。

我将工作人员的数量减少到 3 人,并为每个工作人员分配了 2 个线程,现在我再也看不到这个问题了。

我无法从超时中获得堆栈跟踪,但这似乎在一定数量的工作人员之后无法处理它们?

( unconfirmed - Bugs -

最有用的评论

任何还有这个问题的人,除了增加超时和更改工作类类型之外,请检查应用程序的资源可用性

当我尝试使用 Docker Swarm 部署我的应用程序时遇到了这个问题,并意识到我限制了应用程序的资源太少。 增加资源为我解决问题

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

我认为这不是错误,而是我们配置应用程序的方式

所有18条评论

当一个工人超时时,这意味着它没有及时通知仲裁者它还活着。 您是否在请求期间执行的任何任务可能需要比超时更长的时间?

@jseaido颠簸。

抱歉@benoitc 回复晚了。 我看到的问题实际上是执行此操作的非活动线程。 我的活动线程不会超时,我的非活动线程在较少负载下会给出更多严重的超时错误,而不仅仅是优雅地超时。 我从 gevent 切换到了龙卷风,这似乎解决了挂起问题,但我仍然看到 3 名工作人员每 30 秒持续给出一次临界超时。 如果是正常超时,则不应是严重错误。

我面临着完全相同的问题。
独角兽 19.7.1
gevent 1.2.1
蟒蛇 3.5.3
在Docker中运行,镜像基于官方“ python:3.5

@jseaidou从仲裁者对它的反应一个正常的超时。 这很关键,因为它通常不应该发生。

很可能您的一名工人正在执行阻止操作,以防止 gunicorn 工人通知仲裁者。 如果您的操作时间很长,请确保不时通过睡眠等方式触发 geven 调度程序。 或者任何也可以调用龙卷风调度程序的东西。

我怎样才能重现这个问题?

@saabeilin一样 ^^

我看到了同样的事情:即使在没有请求的情况下,工作人员也会超时。 我所做的只是在 AWS ECS 上启动了我的容器。

[2017-06-27 20:41:56 +0000] [1] [DEBUG] Current configuration:
proxy_protocol: False
worker_connections: 1000
statsd_host: None
max_requests_jitter: 0
post_fork: <function post_fork at 0x7f6bbc3f1938>
errorlog: -
enable_stdio_inheritance: False
worker_class: sync
ssl_version: 2
suppress_ragged_eofs: True
syslog: False
syslog_facility: user
when_ready: <function when_ready at 0x7f6bbc3f1668>
pre_fork: <function pre_fork at 0x7f6bbc3f17d0>
cert_reqs: 0
preload_app: False
keepalive: 2
accesslog: -
group: 0
graceful_timeout: 30
do_handshake_on_connect: False
spew: False
workers: 4
proc_name: None
sendfile: None
pidfile: None
umask: 0
on_reload: <function on_reload at 0x7f6bbc3f1500>
pre_exec: <function pre_exec at 0x7f6bbc3f1ed8>
worker_tmp_dir: None
limit_request_fields: 100
pythonpath: None
on_exit: <function on_exit at 0x7f6bbc3f7758>
config: None
logconfig: None
check_config: False
statsd_prefix:
secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'}
reload_engine: auto
proxy_allow_ips: ['127.0.0.1']
pre_request: <function pre_request at 0x7f6bbc3f70c8>
post_request: <function post_request at 0x7f6bbc3f71b8>
forwarded_allow_ips: ['127.0.0.1']
worker_int: <function worker_int at 0x7f6bbc3f1c08>
raw_paste_global_conf: []
threads: 1
max_requests: 0
chdir: /opt/app
daemon: False
user: 0
limit_request_line: 4094
access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"
certfile: None
on_starting: <function on_starting at 0x7f6bbc3f1398>
post_worker_init: <function post_worker_init at 0x7f6bbc3f1aa0>
child_exit: <function child_exit at 0x7f6bbc3f7320>
worker_exit: <function worker_exit at 0x7f6bbc3f7488>
paste: None
default_proc_name: app:app
syslog_addr: udp://localhost:514
syslog_prefix: None
ciphers: TLSv1
worker_abort: <function worker_abort at 0x7f6bbc3f1d70>
loglevel: DEBUG
bind: ['0.0.0.0:5005']
raw_env: []
initgroups: False
capture_output: False
reload: False
limit_request_field_size: 8190
nworkers_changed: <function nworkers_changed at 0x7f6bbc3f75f0>
timeout: 30
keyfile: None
ca_certs: None
tmp_upload_dir: None
backlog: 2048
logger_class: gunicorn.glogging.Logger
[2017-06-27 20:41:56 +0000] [1] [INFO] Starting gunicorn 19.7.1
[2017-06-27 20:41:56 +0000] [1] [DEBUG] Arbiter booted
[2017-06-27 20:41:56 +0000] [1] [INFO] Listening at: http://0.0.0.0:5005 (1)
[2017-06-27 20:41:56 +0000] [1] [INFO] Using worker: sync
[2017-06-27 20:41:56 +0000] [8] [INFO] Booting worker with pid: 8
[2017-06-27 20:41:57 +0000] [9] [INFO] Booting worker with pid: 9
[2017-06-27 20:41:57 +0000] [10] [INFO] Booting worker with pid: 10
[2017-06-27 20:41:57 +0000] [12] [INFO] Booting worker with pid: 12
[2017-06-27 20:41:57 +0000] [1] [DEBUG] 4 workers
[2017-06-27 20:42:15 +0000] [10] [DEBUG] Closing connection.
[2017-06-27 20:42:15 +0000] [8] [DEBUG] Closing connection.
[2017-06-27 20:42:45 +0000] [8] [DEBUG] Closing connection.
[2017-06-27 20:42:45 +0000] [10] [DEBUG] Closing connection.
[2017-06-27 20:42:46 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:9)
[2017-06-27 20:42:46 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:12)
[2017-06-27 20:42:46 +0000] [9] [INFO] Worker exiting (pid: 9)
[2017-06-27 20:42:46 +0000] [12] [INFO] Worker exiting (pid: 12)
[2017-06-27 20:42:46 +0000] [1] [DEBUG] 3 workers
[2017-06-27 20:42:46 +0000] [24] [INFO] Booting worker with pid: 24
[2017-06-27 20:42:46 +0000] [25] [INFO] Booting worker with pid: 25
[2017-06-27 20:42:46 +0000] [1] [DEBUG] 4 workers

在本地运行时不会发生这种情况。 :-/

看起来切换到gevent工人已经为我解决了这个问题。 ¯\_(ツ)_/¯

我想是#1194 的重复。

我最近看到这种情况反复发生,对我来说,这似乎与让笔记本电脑进入睡眠状态有关。 当我打开盖子时,会显示一堆这样的消息。 不确定这有帮助,但我想我会提到它......

gunicorn --daemon --workers 2 --timeout 120 --bind 127.0.0.1:4000 --pid /var/run/mshc_admin.pid --user danilovskoe --group danilovskoe --chdir /home/danilovskoe/mshc2/src /flask/ --env MSHC_PRODUCTION=/etc/monit/mshc.config.py admin_ gunicorn:app

超时 30 秒
获取请求

Ubuntu 16.04
烧瓶 0.12.2
Python 3.6.3(默认,2017 年 10 月 4 日,02:55:45)
[GCC 5.4.0 20160609] 在 linux 上
gunicorn(版本 19.7.1)

我遇到了麻烦。

启动应用程序后,它就可以工作了。 但只有当有请求时,才会触发[CRITICAL] WORKER TIMEOUT 。 例如,

[2018-01-02 16:38:03 +0800] [24355] [INFO] Starting gunicorn 19.7.1
[2018-01-02 16:38:03 +0800] [24355] [DEBUG] Arbiter booted
[2018-01-02 16:38:03 +0800] [24355] [INFO] Listening at: http://0.0.0.0:8080 (24355)
[2018-01-02 16:38:03 +0800] [24355] [INFO] Using worker: gevent
[2018-01-02 16:38:03 +0800] [24358] [INFO] Booting worker with pid: 24358
[2018-01-02 16:38:03 +0800] [24355] [DEBUG] 1 workers

[2018-01-02 16:38:10 +0800] [24358] [DEBUG] GET /v1/bj2/CC/uuid
[2018-01-02 16:38:10 +0800] [24358] [DEBUG] Closing connection. 
[2018-01-02 16:38:41 +0800] [24355] [CRITICAL] WORKER TIMEOUT (pid:24358)
[2018-01-02 16:38:41 +0800] [24358] [INFO] Worker exiting (pid: 24358)
[2018-01-02 16:38:41 +0800] [24381] [INFO] Booting worker with pid: 24381

[2018-01-02 16:48:51 +0800] [24355] [CRITICAL] WORKER TIMEOUT (pid:24381)
[2018-01-02 16:48:51 +0800] [24381] [INFO] Worker exiting (pid: 24381)
[2018-01-02 16:48:51 +0800] [24703] [INFO] Booting worker with pid: 24703
[2018-01-02 16:48:51 +0800] [24703] [INFO] worker pid 24703 notify
[2018-01-02 16:48:51 +0800] [24703] [DEBUG] GET /v1/bj2/CC/uuid
[2018-01-02 16:48:51 +0800] [24703] [DEBUG] Closing connection. 
CentOS: 6.7
Python: 3.6.3
Gevent: 1.2.2
Greenlet: 0.4.9
Gunicorn: 19.7.1

RUN CMD: gunicorn --worker-class gevent --log-level debug --bind 0.0.0.0:8080 app

当我将工人班级切换为eventlet ,那就是,
gunicorn --worker-class eventlet --log-level debug --bind 0.0.0.0:8080 app ,
没关系。

注意:我的应用程序运行在物理主机上,既不是虚拟主机也不是云主机。


更新:

所以我想这是 gevent 或 gevent worker 的问题。

有关于 gevent 解决问题和 gevent 导致问题的这个问题的报告。 我无法在这里确定根本原因。 一些报告可能与#1194 相同,但其他报告可能不同。

如果有人可以分享一个最小的案例来重现,那会有所帮助。

我不确定这绝对是同一个问题,但我可以通过以下设置使用 Virtualbox 100% 重现此问题:

主机:Windows 10
来宾:Ubuntu 16.04
独角兽:19.7.1

我通过默认的 NAT 连接在主机和来宾之间转发TCP:8000 。 使用sync工作器,主机上localhost:8000任何请求都会导致这些错误出现在日志中,但是如果我在来宾上发出相同的请求,日志就很清楚了。 切换到--worker-class eventlet将删除跟踪。

我很欣赏 Virtualbox 是一个完全不同的维度,但它听起来与上面描述的非常相似,并且始终可重现(至少对我而言)。

我看到这种情况发生在缓慢的上传中。 在上传(到 Django 站点)期间,如果工作器超时,上传将终止。

@lordmauve如果您使用的是预期的同步工作器。 长请求会阻塞 worker,最终仲裁器会杀死它。 如果您希望长请求成功,您可以使用不同的工作线程类型。

对于阅读此线程的任何人,请以最小的情况重新打开以进行复制。 我在这里看不到任何干净的调查。 对于 AWS / ECS,我仍然保持 #1194 处于打开状态,直到我可以测试我列出的配置 (https://github.com/benoitc/gunicorn/issues/1194#issuecomment-371250650)。

任何还有这个问题的人,除了增加超时和更改工作类类型之外,请检查应用程序的资源可用性

当我尝试使用 Docker Swarm 部署我的应用程序时遇到了这个问题,并意识到我限制了应用程序的资源太少。 增加资源为我解决问题

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

我认为这不是错误,而是我们配置应用程序的方式

@jseaidou从仲裁者对它的反应一个正常的超时。 这很关键,因为它通常不应该发生。

很可能您的一名工人正在执行阻止操作,以防止 gunicorn 工人通知仲裁者。 如果您的操作时间很长,请确保不时通过睡眠等方式触发 geven 调度程序。 或者任何也可以调用龙卷风调度程序的东西。

我怎样才能重现这个问题?

@saabeilin一样 ^^

谢谢,这是有道理的。
对我来说,这是在提供以前从云存储下载的大文件时发生的。
根据请求,文件从云存储检索到本地磁盘,然后流解密到客户端。 从云存储下载工作正常,即使需要 10 分钟或更长时间。
一旦 worker 开始将文件从磁盘流解密到客户端,它会在几百 MB 后死亡,可能是因为它在忙于这个阻塞操作时超时。

此页面是否有帮助?
0 / 5 - 0 等级