似乎已经有几个与[CRITICAL] WORKER TIMEOUT
错误相关的报告,但它只是不断弹出。 这是我的问题。
我正在运行这个 Flask hello world 应用程序。
from flask import Flask
application = Flask(__name__)
@application.route('/')
def hello_world():
return 'Hello, World!'
gunicorn 命令是这样的:
gunicorn -b 0.0.0.0:5000 --log-level=debug hello
这是控制台输出:
[2018-06-05 14:56:21 +0200] [11229] [INFO] Starting gunicorn 19.8.1
[2018-06-05 14:56:21 +0200] [11229] [DEBUG] Arbiter booted
[2018-06-05 14:56:21 +0200] [11229] [INFO] Listening at: http://0.0.0.0:5000 (11229)
[2018-06-05 14:56:21 +0200] [11229] [INFO] Using worker: sync
[2018-06-05 14:56:21 +0200] [11232] [INFO] Booting worker with pid: 11232
[2018-06-05 14:56:21 +0200] [11229] [DEBUG] 1 workers
[2018-06-05 14:56:32 +0200] [11232] [DEBUG] GET /
[2018-06-05 14:56:57 +0200] [11232] [DEBUG] Closing connection.
[2018-06-05 14:57:16 +0200] [11232] [DEBUG] GET /
[2018-06-05 14:57:47 +0200] [11229] [CRITICAL] WORKER TIMEOUT (pid:11232)
[2018-06-05 14:57:47 +0200] [11232] [INFO] Worker exiting (pid: 11232)
[2018-06-05 14:57:47 +0200] [11324] [INFO] Booting worker with pid: 11324
您能否清楚地解释一下为什么我会收到错误以及是否在此示例中出现错误? 我该如何修复它,或者如果它是预期的行为,那么为什么会出现严重错误?
该错误不是预期的,但是您的示例中没有任何内容可以说明它为什么会发生。 告诉我们更多有关您的环境的信息。
告诉我们更多有关您的环境的信息。
我刚刚在一个全新的设置上重现了这个问题,以下是步骤:
mkdir gunicorn
cd gunicorn/
pipenv --python 3.6
pipenv install flask
pipenv install gunicorn
vim hello.py
pipenv shell
gunicorn -b 0.0.0.0:5000 --log-level=debug hello
hello.py
与我在初始报告中发布的 Flask 应用程序完全相同。
下面是完整的日志。
~$ gunicorn -b 0.0.0.0:5000 --log-level=debug hello
[2018-06-06 09:16:21 +0200] [19829] [DEBUG] Current configuration:
config: None
bind: ['0.0.0.0:5000']
backlog: 2048
workers: 1
worker_class: sync
threads: 1
worker_connections: 1000
max_requests: 0
max_requests_jitter: 0
timeout: 30
graceful_timeout: 30
keepalive: 2
limit_request_line: 4094
limit_request_fields: 100
limit_request_field_size: 8190
reload: False
reload_engine: auto
reload_extra_files: []
spew: False
check_config: False
preload_app: False
sendfile: None
reuse_port: False
chdir: /home/dima/work/gunicorn
daemon: False
raw_env: []
pidfile: None
worker_tmp_dir: None
user: 1000
group: 985
umask: 0
initgroups: False
tmp_upload_dir: None
secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'}
forwarded_allow_ips: ['127.0.0.1']
accesslog: None
disable_redirect_access_to_syslog: False
access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"
errorlog: -
loglevel: debug
capture_output: False
logger_class: gunicorn.glogging.Logger
logconfig: None
logconfig_dict: {}
syslog_addr: udp://localhost:514
syslog: False
syslog_prefix: None
syslog_facility: user
enable_stdio_inheritance: False
statsd_host: None
statsd_prefix:
proc_name: None
default_proc_name: hello
pythonpath: None
paste: None
on_starting: <function OnStarting.on_starting at 0x7f9757112d08>
on_reload: <function OnReload.on_reload at 0x7f9757112e18>
when_ready: <function WhenReady.when_ready at 0x7f9757112f28>
pre_fork: <function Prefork.pre_fork at 0x7f9756c230d0>
post_fork: <function Postfork.post_fork at 0x7f9756c231e0>
post_worker_init: <function PostWorkerInit.post_worker_init at 0x7f9756c232f0>
worker_int: <function WorkerInt.worker_int at 0x7f9756c23400>
worker_abort: <function WorkerAbort.worker_abort at 0x7f9756c23510>
pre_exec: <function PreExec.pre_exec at 0x7f9756c23620>
pre_request: <function PreRequest.pre_request at 0x7f9756c23730>
post_request: <function PostRequest.post_request at 0x7f9756c237b8>
child_exit: <function ChildExit.child_exit at 0x7f9756c238c8>
worker_exit: <function WorkerExit.worker_exit at 0x7f9756c239d8>
nworkers_changed: <function NumWorkersChanged.nworkers_changed at 0x7f9756c23ae8>
on_exit: <function OnExit.on_exit at 0x7f9756c23bf8>
proxy_protocol: False
proxy_allow_ips: ['127.0.0.1']
keyfile: None
certfile: None
ssl_version: 2
cert_reqs: 0
ca_certs: None
suppress_ragged_eofs: True
do_handshake_on_connect: False
ciphers: TLSv1
raw_paste_global_conf: []
[2018-06-06 09:16:21 +0200] [19829] [INFO] Starting gunicorn 19.8.1
[2018-06-06 09:16:21 +0200] [19829] [DEBUG] Arbiter booted
[2018-06-06 09:16:21 +0200] [19829] [INFO] Listening at: http://0.0.0.0:5000 (19829)
[2018-06-06 09:16:21 +0200] [19829] [INFO] Using worker: sync
[2018-06-06 09:16:21 +0200] [19832] [INFO] Booting worker with pid: 19832
[2018-06-06 09:16:22 +0200] [19829] [DEBUG] 1 workers
[2018-06-06 09:16:48 +0200] [19832] [DEBUG] GET /
[2018-06-06 09:17:19 +0200] [19829] [CRITICAL] WORKER TIMEOUT (pid:19832)
[2018-06-06 09:17:19 +0200] [19832] [INFO] Worker exiting (pid: 19832)
[2018-06-06 09:17:19 +0200] [19872] [INFO] Booting worker with pid: 19872
^C[2018-06-06 09:17:26 +0200] [19829] [INFO] Handling signal: int
[2018-06-06 09:17:26 +0200] [19872] [INFO] Worker exiting (pid: 19872)
[2018-06-06 09:17:26 +0200] [19829] [INFO] Shutting down: Master
~$ pip list
Package Version
------------ -------
click 6.7
Flask 1.0.2
gunicorn 19.8.1
itsdangerous 0.24
Jinja2 2.10
MarkupSafe 1.0
pip 10.0.1
setuptools 39.2.0
Werkzeug 0.14.1
wheel 0.31.1
@bigunyak我认为这是因为默认超时,您的工作人员已经沉默了 30 秒。 http://docs.gunicorn.org/en/stable/settings.html#timeout
从你的日志中,
[2018-06-05 14:57:16 +0200] [11232] [DEBUG] GET /
[2018-06-05 14:57:47 +0200] [11229] [CRITICAL] WORKER TIMEOUT (pid:11232)
[2018-06-06 09:16:48 +0200] [19832] [DEBUG] GET /
[2018-06-06 09:17:19 +0200] [19829] [CRITICAL] WORKER TIMEOUT (pid:19832)
我看到了同样的事情:即使在没有请求的情况下,工作人员也会超时,使用同步工作人员。
从这个意义上说,临界级别日志相当混乱。
尝试使用 Gevent worker 可以解决这个问题。
从这个意义上说,临界级别日志相当混乱。
没错,那是我最初的问题:如果这是预期的行为,那么为什么会出现严重错误?
获得一些关于为什么需要重新启动工作人员的背景知识也很好,也许这可以添加到设计文档中。
我也看到了这一点(通过使用examples/test.py
和gunicorn test:app -b localhost:9595 --log-level=debug --timeout=5
复制),我同意临界级别有点令人困惑。 我可以将其更改为调试级别。 @benoitc @tilgovi你怎么看?
我认为信息级别可能会好一点。
我在 Win10 上的 MSYS2 也有同样的问题,但最终可以解决。
在...\gunicorn\workers\workertmp.py的notify()中,最初使用的是os.fchmod。 但它在 MSYS 中不起作用。 我没有使用 os.fchmod,而是使用了 os.utime。 代码如下。 我认为它适用于所有平台。
def notify(self):
try:
self.spinner = (self.spinner + 1) % 2
os.fchmod(self._tmp.fileno(), self.spinner)
if PLATFORM.startswith('MSYS') :
os.utime(self._tmp.fileno(), None)
except AttributeError:
# python < 2.6
self._tmp.truncate(0)
os.write(self._tmp.fileno(), b"X")
@berkerpeksag我不希望工作人员因为没有请求发生而退出。 仅当工作人员忙了一段时间 > 到超时时,才会发生此错误。 所以这个错误很关键。 Imo 我们应该改进文档以提供更多用例和对此类错误的响应。
如果在工作人员不忙时错误仍然发生,那么还有其他事情发生,我们可能有错误。
[编辑]
对我来说同样的错误。
使用 Django 1.10 / gunicorn 19.6.0 / Python 2.7.15 在 Debian 8.8 上的 python2.7-alpine 和股票内核 3.16,一切正常。
更新到 Django 1.11 和 gunicorn 19.8.1 后,工作人员在启动时不断失败,并显示 [CRITICAL WORKER TIMEOUT]。
将 gunicorn 降级到 19.6.0 并不能解决问题。
我们将主机内核更新为 4.9.0(已安排),并且工作程序成功启动且没有错误。
但:
我们将尝试使用 gunicorn gevent 来查看我们是否能够让我们的应用重新上线。
将 gunicorn 与 gevent 一起使用并没有修复该错误。
关于这个问题的任何更新?
看起来@neocolor在 MSYS 下发现了一个真正的错误。 它可能值得一个单独的问题。
@bigunyak你在什么平台下运行? 我试图用这个简单的例子来重现,但我不能完全按照上面列出的步骤来做。 这与我在多个框架上在生产中运行多个应用程序的经验一致。 据我所知,工人通知系统最近没有改变。 我的平台是 MacOS 10.13.6 上的 Python 3.7,但我在生产中运行 Gunicorn 并在 Python 2.7 和 3.6.5 上为多个应用程序同步工作线程,并且只有在有合法的长请求阻塞工作线程时才会看到工作线程超时。
对于@Tberdy :如果您尝试将--worker-tmp-dir
设置
有关 Docker 相关的 tmpfs 问题,另请参阅 #1388。
我有这个问题。
我也有这个问题,直到昨天晚上,gunicorn 同步都运行良好,然后开始报告,使用 gevent 的工人超时 [CRITICAL] 似乎解决了我的问题,但我真的很想知道为什么会这样。
@timoj58 @cjmash你能提供更多关于这个问题的细节吗? 你如何运行 gunicorn(在虚拟机中?,选项......),哪个文件系统,操作系统? 可以帮助复制的东西会非常有帮助:)
@benoitc我正在运行 gunicorn 在 kubernetes 上启动我的 Django 项目我的 gunicorn 参数是 --bind=$port --workers=7 --timeout=1200 --log-level=debug --access-logfile - error-logfile - ”
我从日志中得到的错误
```E [2018-08-09 21:47:56 +0000] [13] [INFO] 使用 pid 启动 worker:13
E [2018-08-09 21:47:56 +0000] [14] [INFO] 使用 pid 启动 worker:14
E [2018-08-09 21:47:56 +0000] [12] [INFO] 使用 pid 启动 worker:12
E [2018-08-09 21:47:56 +0000] [1] [DEBUG] 7 个工人
E [2018-08-09 21:47:56 +0000] [11] [INFO] pid: 11
E [2018-08-09 21:47:55 +0000] [10] [INFO] 使用 pid: 10 的引导工人
E [2018-08-09 21:47:55 +0000] [9] [INFO] 使用 pid 启动 worker:9
E [2018-08-09 21:47:55 +0000] [8] [INFO] 使用 pid 启动 worker:8
E [2018-08-09 21:47:55 +0000] [1] [INFO] 使用工人:同步
E [2018年8月9日21时47分55秒0000] [1] [INFO]听力于: http://0.0.0.0 :4040(1)
E [2018-08-09 21:47:55 +0000] [1] [DEBUG] 仲裁器启动
E [2018-08-09 21:47:55 +0000] [1] [INFO]启动gunicorn 19.7.1
E raw_paste_global_conf: []
E 密码:TLSv1
E do_handshake_on_connect: 假
E suppress_ragged_eofs: 真
E ca_certs:无
E cert_reqs: 0
E ssl_version: 2
E 证书文件:无
E 密钥文件:无
E proxy_allow_ips: ['127.0.0.1']
E proxy_protocol: 假
E on_exit:
Enworkers_changed:
E worker_exit:
E child_exit:
E post_request:
E 预请求:
E pre_exec:
E worker_abort:
E worker_int:
E post_worker_init:
E post_fork:
E pre_fork:
E when_ready:
E on_reload:
E on_starting:
E贴:无
E pythonpath:无
E default_proc_name: art.wsgi
E proc_name: 无
E statsd_prefix:
E statsd_host:无
E enable_stdio_inheritance: 假
E syslog_facility: 用户
E syslog_prefix:无
E 系统日志:错误
E syslog_addr: udp://localhost :514
E 日志配置:无
E logger_class: gunicorn.glogging.Logger
E 捕获输出:假
E 日志级别:调试
E 错误日志:-
E access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(作为”
E 访问日志:-
E forwarded_allow_ips: ['127.0.0.1']
E secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'}
E tmp_upload_dir: 无
E initgroups:假
E umask: 0
E组:0
E用户:0
E worker_tmp_dir: 无
E pidfile: 无
E raw_env: []
E 守护进程:错误
E chdir: /usr/src/app
E 发送文件:无
E preload_app: 假
E check_config: 假
E 喷出:错误
E reload_engine: 自动
E 重新加载:错误
E limit_request_field_size: 8190
E limit_request_fields: 100
E limit_request_line: 4094
E保活:2
E 优雅超时:30
E 超时:1200
E max_requests_jitter: 0
E 最大请求数:0
E worker_connections: 1000
E 线程:1
E worker_class:同步
E工:7人
E 积压:2048
E 绑定:['0.0.0.0:4040']
E 配置:无
E [2018-08-09 21:47:55 +0000] [1] [DEBUG] 当前配置:
I 没有可申请的迁移。
I 运行迁移:
我应用所有迁移:admin、auth、contenttypes、core、dashboard、jet、oauth2_provider、sessions
I 执行的操作:
E [2018-08-09 21:47:20 +0000] [13] [INFO] 工人退出 (pid: 13)
E os.path.dirname(os.path.dirname(__file__)), '.env'))
E /usr/src/app/art/wsgi.py:19: UserWarning: Not reading /usr/src/app/.env - 它不存在。
E [2018-08-09 21:47:00 +0000] [21] [INFO] 使用 pid 引导工人:21
E [2018-08-09 21:47:00 +0000] [1] [INFO] 处理信号:术语
E [2018-08-09 21:46:35 +0000] [12] [INFO] 使用 pid 启动 worker:12
E [2018-08-09 21:46:34 +0000] [13] [INFO] 使用 pid 启动 worker:13
E [2018-08-09 21:46:34 +0000] [11] [INFO] 使用 pid: 11 的引导工人
E [2018-08-09 21:46:34 +0000] [1] [DEBUG] 7 个工人
E [2018-08-09 21:46:34 +0000] [10] [INFO] 使用 pid 引导工人:10
E [2018-08-09 21:46:34 +0000] [9] [INFO] 使用 pid 启动 worker:9
E [2018-08-09 21:46:34 +0000] [8] [INFO] 使用 pid 启动 worker:8
E [2018-08-09 21:46:34 +0000] [7] [INFO] 使用 pid 启动 worker:7
E [2018-08-09 21:46:34 +0000] [1] [INFO] 使用工人:同步
E [2018-08-09 21:46:34 +0000] [1] [INFO] 听:http: //0.0.0.0 :4040 (1)
E [2018-08-09 21:46:34 +0000] [1] [DEBUG] 仲裁器启动
E [2018-08-09 21:46:34 +0000] [1] [INFO]启动gunicorn 19.7.1
E raw_paste_global_conf: []
E 密码:TLSv1
E do_handshake_on_connect: 假
E suppress_ragged_eofs: 真
E ca_certs:无
E cert_reqs: 0
E ssl_version: 2
E 证书文件:无
E 密钥文件:无
E proxy_allow_ips: ['127.0.0.1']
E proxy_protocol: 假
E on_exit:
Enworkers_changed:
E worker_exit:
E child_exit:
E post_request:
E 预请求:
E pre_exec:
E worker_abort:
E worker_int:
E post_worker_init:
E post_fork:
E pre_fork:
E when_ready:
E on_reload:
E on_starting:
E贴:无
E pythonpath:无
E default_proc_name: art.wsgi
E proc_name: 无
E statsd_prefix:
E statsd_host:无
E enable_stdio_inheritance: 假
E syslog_facility: 用户
E syslog_prefix:无
E 系统日志:错误
E syslog_addr: udp://localhost :514
E 日志配置:无
E logger_class: gunicorn.glogging.Logger
E 捕获输出:假
E 日志级别:调试
E 错误日志:-
E access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(作为”
E 访问日志:-
E forwarded_allow_ips: ['127.0.0.1']
E secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'}
E tmp_upload_dir: 无
E initgroups:假
E umask: 0
E组:0
E用户:0
E worker_tmp_dir: 无
E pidfile: 无
E raw_env: []
E 守护进程:错误
E chdir: /usr/src/app
E 发送文件:无
E preload_app: 假
E check_config: 假
E 喷出:错误
E reload_engine: 自动
E 重新加载:错误
E limit_request_field_size: 8190
E limit_request_fields: 100
E limit_request_line: 4094
E保活:2
E 优雅超时:30
E 超时:1200
E max_requests_jitter: 0
E 最大请求数:0
E worker_connections: 1000
E 线程:1
E worker_class:同步
E工:7人
E 积压:2048
E 绑定:['0.0.0.0:4040']
E 配置:无
E [2018-08-09 21:46:34 +0000] [1] [DEBUG] 当前配置:
``
这次我努力重现这个问题,但它仍然存在于最新的 gunicorn 版本 19.9.0 中。
重现它的步骤与我在这篇文章中描述的完全相同。
我的系统是 Arch Linux x86_64 GNU/Linux(内核 4.17.2-1-ARCH),Python 3.6.5
这是一个新的日志跟踪。
~$ gunicorn -b 0.0.0.0:5000 --log-level=debug hello
[2018-08-10 09:48:40 +0200] [23114] [DEBUG] Current configuration:
config: None
bind: ['0.0.0.0:5000']
backlog: 2048
workers: 1
worker_class: sync
threads: 1
worker_connections: 1000
max_requests: 0
max_requests_jitter: 0
timeout: 30
graceful_timeout: 30
keepalive: 2
limit_request_line: 4094
limit_request_fields: 100
limit_request_field_size: 8190
reload: False
reload_engine: auto
reload_extra_files: []
spew: False
check_config: False
preload_app: False
sendfile: None
reuse_port: False
chdir: /home/dima/lerning/python/modules/gunicorn
daemon: False
raw_env: []
pidfile: None
worker_tmp_dir: None
user: 1000
group: 985
umask: 0
initgroups: False
tmp_upload_dir: None
secure_scheme_headers: {'X-FORWARDED-PROTOCOL': 'ssl', 'X-FORWARDED-PROTO': 'https', 'X-FORWARDED-SSL': 'on'}
forwarded_allow_ips: ['127.0.0.1']
accesslog: None
disable_redirect_access_to_syslog: False
access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%(a)s"
errorlog: -
loglevel: debug
capture_output: False
logger_class: gunicorn.glogging.Logger
logconfig: None
logconfig_dict: {}
syslog_addr: udp://localhost:514
syslog: False
syslog_prefix: None
syslog_facility: user
enable_stdio_inheritance: False
statsd_host: None
statsd_prefix:
proc_name: None
default_proc_name: hello
pythonpath: None
paste: None
on_starting: <function OnStarting.on_starting at 0x7f5f8b9dad08>
on_reload: <function OnReload.on_reload at 0x7f5f8b9dae18>
when_ready: <function WhenReady.when_ready at 0x7f5f8b9daf28>
pre_fork: <function Prefork.pre_fork at 0x7f5f8b4ec0d0>
post_fork: <function Postfork.post_fork at 0x7f5f8b4ec1e0>
post_worker_init: <function PostWorkerInit.post_worker_init at 0x7f5f8b4ec2f0>
worker_int: <function WorkerInt.worker_int at 0x7f5f8b4ec400>
worker_abort: <function WorkerAbort.worker_abort at 0x7f5f8b4ec510>
pre_exec: <function PreExec.pre_exec at 0x7f5f8b4ec620>
pre_request: <function PreRequest.pre_request at 0x7f5f8b4ec730>
post_request: <function PostRequest.post_request at 0x7f5f8b4ec7b8>
child_exit: <function ChildExit.child_exit at 0x7f5f8b4ec8c8>
worker_exit: <function WorkerExit.worker_exit at 0x7f5f8b4ec9d8>
nworkers_changed: <function NumWorkersChanged.nworkers_changed at 0x7f5f8b4ecae8>
on_exit: <function OnExit.on_exit at 0x7f5f8b4ecbf8>
proxy_protocol: False
proxy_allow_ips: ['127.0.0.1']
keyfile: None
certfile: None
ssl_version: 2
cert_reqs: 0
ca_certs: None
suppress_ragged_eofs: True
do_handshake_on_connect: False
ciphers: TLSv1
raw_paste_global_conf: []
[2018-08-10 09:48:40 +0200] [23114] [INFO] Starting gunicorn 19.9.0
[2018-08-10 09:48:40 +0200] [23114] [DEBUG] Arbiter booted
[2018-08-10 09:48:40 +0200] [23114] [INFO] Listening at: http://0.0.0.0:5000 (23114)
[2018-08-10 09:48:40 +0200] [23114] [INFO] Using worker: sync
[2018-08-10 09:48:40 +0200] [23117] [INFO] Booting worker with pid: 23117
[2018-08-10 09:48:40 +0200] [23114] [DEBUG] 1 workers
[2018-08-10 09:48:45 +0200] [23117] [DEBUG] GET /
[2018-08-10 09:48:54 +0200] [23117] [DEBUG] GET /
[2018-08-10 09:49:00 +0200] [23117] [DEBUG] GET /
[2018-08-10 09:49:18 +0200] [23117] [DEBUG] Closing connection.
[2018-08-10 09:49:18 +0200] [23117] [DEBUG] GET /
[2018-08-10 09:49:23 +0200] [23117] [DEBUG] GET /
[2018-08-10 09:49:37 +0200] [23117] [DEBUG] Closing connection.
[2018-08-10 09:49:37 +0200] [23117] [DEBUG] GET /
[2018-08-10 09:49:50 +0200] [23117] [DEBUG] Closing connection.
[2018-08-10 09:51:11 +0200] [23117] [DEBUG] GET /
[2018-08-10 09:51:13 +0200] [23117] [DEBUG] GET /
[2018-08-10 09:51:43 +0200] [23114] [CRITICAL] WORKER TIMEOUT (pid:23117)
[2018-08-10 09:51:43 +0200] [23117] [INFO] Worker exiting (pid: 23117)
[2018-08-10 09:51:44 +0200] [23229] [INFO] Booting worker with pid: 23229
和之前一样,我只是在 Chromium 中点击了http://0.0.0.0 :5000/ 来测试它。
下面是 Pipfile 和 Pipfile.lock 的内容,供大家查看具体环境。
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"
[packages]
flask = "*"
gunicorn = "*"
[dev-packages]
[requires]
python_version = "3.6"
{
"_meta": {
"hash": {
"sha256": "81cb5d5f0b11719d8d9c5ec9cc683fdcf959c652fda256d5552a82d0f459a99c"
},
"pipfile-spec": 6,
"requires": {
"python_version": "3.6"
},
"sources": [
{
"name": "pypi",
"url": "https://pypi.org/simple",
"verify_ssl": true
}
]
},
"default": {
"click": {
"hashes": [
"sha256:29f99fc6125fbc931b758dc053b3114e55c77a6e4c6c3a2674a2dc986016381d",
"sha256:f15516df478d5a56180fbf80e68f206010e6d160fc39fa508b65e035fd75130b"
],
"version": "==6.7"
},
"flask": {
"hashes": [
"sha256:2271c0070dbcb5275fad4a82e29f23ab92682dc45f9dfbc22c02ba9b9322ce48",
"sha256:a080b744b7e345ccfcbc77954861cb05b3c63786e93f2b3875e0913d44b43f05"
],
"index": "pypi",
"version": "==1.0.2"
},
"gunicorn": {
"hashes": [
"sha256:aa8e0b40b4157b36a5df5e599f45c9c76d6af43845ba3b3b0efe2c70473c2471",
"sha256:fa2662097c66f920f53f70621c6c58ca4a3c4d3434205e608e121b5b3b71f4f3"
],
"index": "pypi",
"version": "==19.9.0"
},
"itsdangerous": {
"hashes": [
"sha256:cbb3fcf8d3e33df861709ecaf89d9e6629cff0a217bc2848f1b41cd30d360519"
],
"version": "==0.24"
},
"jinja2": {
"hashes": [
"sha256:74c935a1b8bb9a3947c50a54766a969d4846290e1e788ea44c1392163723c3bd",
"sha256:f84be1bb0040caca4cea721fcbbbbd61f9be9464ca236387158b0feea01914a4"
],
"version": "==2.10"
},
"markupsafe": {
"hashes": [
"sha256:a6be69091dac236ea9c6bc7d012beab42010fa914c459791d627dad4910eb665"
],
"version": "==1.0"
},
"werkzeug": {
"hashes": [
"sha256:c3fd7a7d41976d9f44db327260e263132466836cef6f91512889ed60ad26557c",
"sha256:d5da73735293558eb1651ee2fddc4d0dedcfa06538b8813a2e20011583c9e49b"
],
"version": "==0.14.1"
}
},
"develop": {}
}
仅供参考,我也经常看到这种失败:
nohup gunicorn -w 8 --access-logfile=- --bind 127.0.0.1:5000 wsgi &
我只有一个 wsgi.py
from chart_api import application
if __name__ == "__main__":
application.run()
如果您希望我尝试/实验任何内容,或者您希望我检查日志中的具体内容,请告诉我。 我在 GCP VM 上运行 Flask。
抱歉回复晚了。 我正在运行它
gunicorn --log-file=/home/ubuntu/log/gunicorn.log predictor_ api:app -b localhost:5000 &
我确实使用了 gevent 设置等,但是为了解决问题,我已经改变了我需要它的设计,因此上面的基本设置(也失败了,但如果没有 gevent,这是可以预料的)
Python 3.6 版
环境:aws tensorflow_p36 优化(ubuntu)
nginx 坐在 gunicorn 前面,它正在执行一个烧瓶应用程序。
烧瓶版本 1.0.2
nginx 版本 1.10.3
gunicorn 版本 19.9.0
我确实更改了 nginx 超时,以防万一这可能导致它。
gunicorn服务器面临同样的问题
# gunicorn Applicat ionServer:app -b 0.0.0.0:6001 -w 8 --threads 4 --backlog 2048 \
# --timeout 120 --graceful-timeout 60 --access-logfile logs/access.log \
烧瓶==0.12.1
枪炮==19.7.1
当我使用上述命令启动服务器时,我的系统冻结了一段时间并且工作进程 pid 继续启动,尽管我保持超时 120 秒,并且服务器不接受单个请求。
关于这个问题的任何更新? 我有同样的问题
[关键] 工人超时
想知道是否有人在 Docker 镜像中成功复制了这个?
在以 gunicorn -k gevent --threads 4 开头的现有应用程序上尝试实现 datadog 的 ddtrace-run worker 时也会看到这一点。
我以前从未见过的 SystemExit 的有趣痕迹......
[2018-11-07 11:11:50 +0000] [15987] [INFO] Booting worker with pid: 15987
[2018-11-07 11:11:50 +0000] [15977] [DEBUG] 1 workers
[2018-11-07 11:12:20 +0000] [15977] [CRITICAL] WORKER TIMEOUT (pid:15987)
Exception SystemExit: 1 in <bound method LibevLoop._loop_will_run of <cassandra.io.libevreactor.LibevLoop object at 0x7f3cb66d4a50>> ignored
我可以通过匹配工作线程数和线程数来解决这个问题。
我已经设置了workers = (2 * cpu_count) + 1
并且没有设置线程。
一旦我改变了threads = workers
,一切就开始正常了。 以防万一,如果这对某人有帮助。
这是现在的样子
def run(host='0.0.0.0', port=8080, workers=1 + (multiprocessing.cpu_count() * 2)):
"""Run the app with Gunicorn."""
if app.debug:
app.run(host, int(port), use_reloader=False)
else:
gunicorn = WSGIApplication()
gunicorn.load_wsgiapp = lambda: app
gunicorn.cfg.set('bind', '%s:%s' % (host, port))
gunicorn.cfg.set('workers', workers)
gunicorn.cfg.set('threads', workers)
gunicorn.cfg.set('pidfile', None)
gunicorn.cfg.set('worker_class', 'sync')
gunicorn.cfg.set('keepalive', 10)
gunicorn.cfg.set('accesslog', '-')
gunicorn.cfg.set('errorlog', '-')
gunicorn.cfg.set('reload', True)
gunicorn.chdir()
gunicorn.run()
我在 AWS Elastic Beanstalk 上使用单个 Docker 容器运行 Django 时遇到了这个问题。 我通过修复我的安全组解决了这个问题,以确保我的 EC2 实例可以与我的 RDS 实例通信。 我意识到这可能不是 99% 的人在这个问题上的解决方案,但我留下这个笔记是为了帮助其他人避免在这个兔子洞中浪费时间。
在我的情况下,问题是通过执行systemctl daemon-reload
。
长话短说,我知道默认超时为 30 秒,但无法更改它,直到我认为我当然必须重新加载 systemd 守护程序才能将更改应用于服务。
@bigunyak @benoitc @tilgovi
经过长时间的 google goose 追逐和一些实验,我相信这个问题的根本原因是 chrome 的“预连接/预测服务”(Chrome 和 Chromium 中默认启用)。
@jeiting对这个问题写了一篇很好的文章
https://hackernoon.com/chrome-preconnect-breaks-singly-threaded-servers-95944be16400
一些补充阅读:
https://github.com/corydolphin/flask-cors/issues/147
https://github.com/pallets/flask/issues/2169
TLDR
在某些情况下,Chrome/Chromium 会打开并保持一个“空”的 TCP 连接(即它预测它将很快获取另一个资源)。 如果“空”TCP 连接首先访问您的 gunicorn 服务器,则来自 chrome 的任何后续“真实”请求都可能卡在“空”请求后面,直到处理“空”请求的工作人员超时为止。 如果您只在 gunicorn 中运行单个同步工作线程,则更有可能发生这种情况。 但是正如我的实验发现的那样,即使您正在运行多个同步工作器,它也可能发生。
我的环境
FROM ubuntu:18.04
...
RUN pip3 install Flask==1.0.2
RUN pip3 install gunicorn==19.9.0
RUN pip3 install flask-cors==3.0.6
......
实验一
Gunicorn 配置:1 个同步工作器(默认 30 秒超时)
Firefox:几乎在每次反应页面加载时,CORS OPTIONS 请求都会被阻止 5 秒,然后成功。
Chromium:在每次响应页面加载时,CORS OPTIONS 请求都会被阻止 1.5 分钟!!! 然后成功。
Chromium(预测服务已禁用):一切正常
Chrome:一切正常
实验二
Gunicorn 配置:4 个同步工作者(默认 30 秒超时)
Firefox:一切正常
Chromium:在每 3 次反应页面加载时,CORS OPTIONS 请求被阻止 30 秒然后成功。
Chromium(预测服务已禁用):一切正常
Chrome:一切正常
实验三
Gunicorn 配置:8 个同步工作者(默认 30 秒超时)
Firefox:一切正常
Chromium:一切正常
Chrome:一切正常
实验四
使用threaded=True
运行 Flask 开发服务器
Firefox:一切正常
Chromium:一切正常
Chrome:一切正常
实验总结
解决方案
在生产中:最简单的解决方法是将 nginx 放在 gunicorn 前面。 如果您想了解 nginx 解决此问题的原因,这里有一篇很好的文章解释了它: https :
在开发中:最简单的解决方法是使用threaded=True
运行 Flask 开发服务器。 或者您可以在 Chrome/Chromium 中禁用预测服务。
gunicorn 调试改进
为了在将来帮助调试此类问题,我认为最好在同步工作线程中的select()
和accept()
调用旁边添加调试日志语句。
https://github.com/benoitc/gunicorn/blob/e974f30517261b2bc95cfb2017a8688f367c8bf3/gunicorn/workers/sync.py#L26
https://github.com/benoitc/gunicorn/blob/e974f30517261b2bc95cfb2017a8688f367c8bf3/gunicorn/workers/sync.py#L34
这将表明工作人员已接受新的 TCP 连接,但未接收任何数据。
@asnisarenko超级写,谢谢。 #1929 是另一个不寻常的慢客户端案例,它在单线程服务器中产生类似的症状 - 在这种情况下,TLS 与非 TLS 端口的握手看起来像一个写入缓慢的客户端,因为它无法快速发送合理的标头.
它可能是 Gunicorn,因为单线程同步工作者将需要一些新的可调参数,对于在合理时间内无法发送至少第一个请求标头行(如果不是所有标头)的客户端的积极客户端丢弃。
如果您的应用发生这种情况,您可以添加一些临时诊断代码:
def trace_on_abort():
import signal
import traceback
def print_trace(sig, frame):
print(''.join(traceback.format_stack(frame)))
signal.signal(signal.SIGABRT, print_trace)
希望这应该揭示您的应用程序挂在哪里。
例如,我总算import flask
之前gevent.monkey.patch_all()
所以我的瓶的app._before_request_lock
结束了非GEVENT锁(即普通未打补丁的threading.Lock
)。 在这种情况下,在应用程序启动时连续两次请求将导致它挂起(第二个请求将锁定整个线程)。 但这是我的错误,您的错误可能有所不同。
@asnisarenko我不知道你为什么会挂起。 您绝对_不需要_每个连接都需要一个工作线程,因为每个工作线程都可以协同处理数千个连接(只要处理代码不独占 CPU / 锁定整个线程)。 具体来说,如果浏览器停止请求,它只是意味着当 gunicorn read()
来自套接字时,它会阻止一个 greenlet,但是由于read
应该是猴子补丁,它会屈服于其他小绿叶。
@ikonst
这个问题是在谈论使用默认配置运行 gunicorn。 默认工人类是sync
http://docs.gunicorn.org/en/stable/settings.html#worker -class
sync
worker 使用 pre-fork 模型,每个 worker 一次处理一个 TCP 连接/请求。
我不知道是什么导致了这个问题,但是从默认的sync
工人类型切换到eventlet
解决了这个问题:
CMD pipenv run gunicorn webapp -b 0.0.0.0:8080 -k eventlet
祝你好运。
也许这只会对我有帮助,但由于我花了 7 小时来调试这个问题(一个在 EC2 上的 Docker 中运行的 Flask/Gunicorn 应用程序),如果我能把这个麻烦留给少数人,那就是一个小小的胜利。
容器内存限制过低。
如果我将来有内存泄漏,我会尝试设置更高的内存限制,但现在,没有限制。
谢谢
def trace_on_abort(): import signal import traceback def print_trace(sig, frame): print(''.join(traceback.format_stack(frame))) signal.signal(signal.SIGABRT, print_trace)
你太帮我了。 EHU )))
这个trace_on_abort()
方法去哪里了? 在应用程序代码文件中? 它需要注释吗?
@mattg-vbt 在需要调试时将其添加到应用程序的开头,并在完成调试后将其删除
@ikonst我将此添加到我的应用程序中,但我没有看到它受到影响。 我得到了工人超时,但这个方法没有被命中。
@mattg-vbt 你能试试做kill -ABRT $pid
来查看调用的print_trace
函数吗? (这个想法是当你的工人超时时你会从 werkzeug 获得 SIGABRT,但让我们首先检查它是否被调用)
@asnisarenko对于我们中不太精明的人,我将如何更新 procfile?
web gunicorn app:app -k gevent --worker-connections 1000
?
@SumNeuron
如果您正在使用 gevent 工作人员(而不是同步工作人员),那么您不应该遇到这个问题。 所以你发布的命令看起来不错。
我只有在初始化时才会遇到 gevent 工作人员的这个问题,这有点烦人,因为我在启动我的应用程序之前正在处理一些任务。 但我现在设置了一个很高的超时时间。
我在这里发布了一个可重现的测试仓库:https://github.com/zamponotiropita/test-gunicorn-worker-timeout -> test_0 失败,test_1 和 test_2 通过
@zamponotiropita您是否尝试在分叉之前按每个工人或每个应用程序执行此操作?
@ikonst请检查运行文件run.sh
,它是每个工人的。 问题不是与预加载有关,但是我在预加载时连接到数据库时遇到问题,因为应用对象(以及与数据库连接一起)在分叉时被复制并通过了进程 -> 我的数据库无法处理主人和工人的相同连接,我找不到解决方法
我有一个类似的问题。 我正在尝试使用 Flask 即时生成大量数据
此方法失败,因为在--timeout
设置的任何内容过期后工作人员超时。 重现的最小示例:
test_gunicorn_timeout.py
import flask
from time import sleep
app = flask.Flask(__name__)
@app.route('/')
def gunicorn_timeout():
def generator():
for _ in range(10):
yield b'Yet another line...'
sleep(2)
return flask.Response(generator(), mimetype='text/plain')
然后运行gunicorn --timeout 10 test_gunicorn_timeout:app
并在 10 秒后请求localhost:8000
,您会得到
[CRITICAL] WORKER TIMEOUT
。
我还尝试使用-k gevent
和-k eventlet
,但没有任何改变。
我在 Windows 10 专业版上。 使用 docker 撰写gunicorn app -b 0.0.0.0:8000 -k gevent
通过在我的 python 容器中安装 gevent 为我工作
如何安装 gevent
然后运行
gunicorn --timeout 10 test_gunicorn_timeout:app
并在 10 秒后请求localhost:8000
,您会得到一个
[CRITICAL] WORKER TIMEOUT
。我还尝试使用
-k gevent
和-k eventlet
,但没有任何改变。
@ltskv
您找到 [CRITICAL] WORKER TIMEOUT 问题的解决方案了吗?
我试图在 heroku(使用 gunicorn)上部署的烧瓶流端点也有类似的问题。 在那里,只要在 30 秒内发送了一些数据,代理前端就应该保持连接处于活动状态,但是如果它在 30 秒内没有完成,即使它仍在运行并生成数据,似乎 gunicorn 只是终止了该进程。
在这一点上,gunicorn 文档对我来说并不完全清楚。 对于 --timeout 它说Workers silent for more than this many seconds are killed and restarted.
但似乎工人在 30 秒后被杀死,即使他们仍然产生数据?
在这一点上,gunicorn 文档对我来说并不完全清楚。 对于 --timeout 它说工人沉默超过这么多秒被杀死并重新启动。 但似乎工人在 30 秒后被杀死,即使他们仍然产生数据?
@kurt-hectic 应该改进文档。 静默,我们的意思是从仲裁进程的角度来看静默,它通过一个临时文件与工人通信。 如果工作人员正忙于发送数据,则不会更新该文件。 从仲裁者的角度来看,工人正在丢失心跳。
另见#1974。
使用除默认值之外的任何工作器,同步工作器应该减轻流式传输大型主体的问题,因为其他工作器即使在处理请求时也会心跳临时文件。
@kurt-hectic 我再次重新检查了-k gevent
选项并在生成器迭代之间插入了sleep(0)
并且它确实对我有用(我不确定为什么它当时不起作用我发布了这个问题)。
--超时=5
这是导致此问题的最常见原因。
我希望我的解决方案可以帮助你。 几天前我遇到了这个关键的工人超时问题并尝试了一些解决方案。 它现在运作良好。
以下是我的理解和解决方案:
它无法启动工作程序,因为它需要更多时间来加载包,例如 tensorflow 后端,以启动服务。 因此,当您遇到应用程序启动时间缓慢时,请尝试在 gunicorn 中启用预加载选项(请参阅 https://devcenter.heroku.com/articles/python-gunicorn#advanced-configuration)。
gunicorn hello:app --preload
默认超时时间为 30 秒。 如果您的应用程序确实需要很多时间来完成 api,请增加超时。
gunicorn hello:app --timeout 10
但是,从我的角度来看,如果 api 需要超过 1 分钟才能完成是没有意义的。 如果是这样,请尝试在您的代码中取得一些进展。
我今天遇到了同样的问题。 在我的情况下,api 需要大约一分钟来计算数据并返回到客户端,这导致了 CRITICAL WORKER TIMEOUT 错误。 我通过将 gunicorn 的超时标志增加到一分钟以上来解决它 - 它有效,没有看到问题再次出现。 希望这可以帮助。 我正在使用 uvicorn.workers.UvicornWorker。
我通过向 gnuicorn 添加额外的工人来解决这个问题:
web: gunicorn --workers=3 BlocAPI:app --log-file -
不知道为什么。
也许你陷入了僵局? 您的应用程序是否向自身发出请求?
在 2020 年 1 月 5 日星期日 10:52 alpinechicken, notifications @github.com 写道:
我通过向 gnuicorn 添加额外的工人来解决这个问题:
网络:gunicorn --workers=3 BlocAPI:app --log-file -
不知道为什么。
—
您收到此消息是因为您发表了评论。
直接回复本邮件,在GitHub上查看
https://github.com/benoitc/gunicorn/issues/1801?email_source=notifications&email_token=AAAEQJVQRCW3C63EZJWIN5DQ4G3WTA5CNFSM4FDLD5PKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63KLODNTX5200000000000000000000000000000000001
或取消订阅
https://github.com/notifications/unsubscribe-auth/AAAEQJXZM4NLK56DZMFSZALQ4G3WTANCNFSM4FDLD5PA
.
是的,一条路线呼叫另一条路线 - 那很糟糕吗?
这意味着您至少需要两名工作人员,否则您的服务器将
僵局。 请求将等待服务器响应第二个
请求(将排队)。
每个工作人员都会收到一个并发请求。
在 2020 年 1 月 6 日星期一 02:45 alpinechicken, notifications @github.com 写道:
是的,一条路线呼叫另一条路线 - 那很糟糕吗?
—
您收到此消息是因为您发表了评论。
直接回复本邮件,在GitHub上查看
https://github.com/benoitc/gunicorn/issues/1801?email_source=notifications&email_token=AAAEQJSFEFBBI6AMZJCM4C3Q4KLOJA5CNFSM4FDLD5PKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXZHJC8000000000000引
或取消订阅
https://github.com/notifications/unsubscribe-auth/AAAEQJXTCPOFIZJU5PUPOODQ4KLOJANCNFSM4FDLD5PA
.
啊,有道理。 谢谢!
2020 年 1 月 7 日,星期二,上午 6:23, bobf [email protected]写道:
这意味着您至少需要两名工作人员,否则您的服务器将
僵局。 请求将等待服务器响应第二个
请求(将排队)。每个工作人员都会收到一个并发请求。
在 2020 年 1 月 6 日星期一 02:45 alpinechicken, notifications @github.com 写道:
是的,一条路线呼叫另一条路线 - 那很糟糕吗?
—
您收到此消息是因为您发表了评论。
直接回复本邮件,在GitHub上查看
<
https://github.com/benoitc/gunicorn/issues/1801?email_source=notifications&email_token=AAAEQJSFEFBBI6AMZJCM4C3Q4KLOJA5CNFSM4FDLD5PKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXWZHJK8000000000000000000000引
,
或取消订阅
<
https://github.com/notifications/unsubscribe-auth/AAAEQJXTCPOFIZJU5PUPOODQ4KLOJANCNFSM4FDLD5PA.
—
您收到此消息是因为您发表了评论。
直接回复本邮件,在GitHub上查看
https://github.com/benoitc/gunicorn/issues/1801?email_source=notifications&email_token=AAH2WRPVPVO2EJ53BKQW5B3Q4OHLRA5CNFSM4FDLD5PKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW6ZKIGDNV7000G43VMVBW6ZKIGDNV700000000007
或取消订阅
https://github.com/notifications/unsubscribe-auth/AAH2WRM2LLIB4O6OHCU5UG3Q4OHLRANCNFSM4FDLD5PA
.
worker_class', '同步')
我可以通过匹配工作线程数和线程数来解决这个问题。
我已经设置了
workers = (2 * cpu_count) + 1
并且没有设置线程。一旦我改变了
threads = workers
,一切就开始正常了。 以防万一,如果这对某人有帮助。这是现在的样子
def run(host='0.0.0.0', port=8080, workers=1 + (multiprocessing.cpu_count() * 2)): """Run the app with Gunicorn.""" if app.debug: app.run(host, int(port), use_reloader=False) else: gunicorn = WSGIApplication() gunicorn.load_wsgiapp = lambda: app gunicorn.cfg.set('bind', '%s:%s' % (host, port)) gunicorn.cfg.set('workers', workers) gunicorn.cfg.set('threads', workers) gunicorn.cfg.set('pidfile', None) gunicorn.cfg.set('worker_class', 'sync') gunicorn.cfg.set('keepalive', 10) gunicorn.cfg.set('accesslog', '-') gunicorn.cfg.set('errorlog', '-') gunicorn.cfg.set('reload', True) gunicorn.chdir() gunicorn.run()
根据 gunicorn 文档,如果提到多个线程,它会将工作类从同步更改为 gthread。
PS:-
如果您尝试使用同步工作线程类型并将线程设置设置为大于 1,则将使用 gthread 工作线程类型。
我的情况:
环境:Ubuntu18.04+ gunicorn+ nginx +flask
pip install gunicorn[gevent] 在我的虚拟环境中
将gunicorn -b localhost:8000 -w 4 web:app
更改gunicorn -b localhost:8000 -k gevent web:app
有用。
感谢这里的每一个人,他们为帮助彼此解决问题做了大量工作。 如果觉得合适,请继续发布到这个问题。
但是,我正在关闭这个问题,因为我认为 Gunicorn 中没有任何错误,我认为没有任何措施可以采取,尽管我很乐意帮助审查试图以某种方式为此添加文档或改进的 PR记录消息。
请不要误解我的意图。 如果您怀疑 Gunicorn 中存在错误并想继续讨论,请这样做。 最好使用重现您的问题的示例应用程序打开新票证。 然而,在这一点上,这个问题有太多不同的问题、解决方案和对话,以致于它是非常易读的。
如果您在没有缓冲反向代理的情况下运行 Gunicorn,您_将_获得默认超时,出于多种原因同步工作程序。 常见的有:
您可以切换到异步或线程工作者类型,或者您可以将 Gunicorn 置于缓冲反向代理之后。 如果您知道超时是由于您自己的代码对外部 API 的调用缓慢或执行了您期望的重要工作,您可以增加--timeout
选项。
这意味着您至少需要两名工作人员,否则您的服务器将陷入僵局。 该请求将一直等到服务器响应第二个请求(将排队)。 每个工作人员都会收到一个并发请求。
…
在 2020 年 1 月 6 日星期一,02:45 alpinechicken, @ 。 * > 写道:是的,一条路线调用另一条路线 - 是不是很糟糕?
调用“重定向”函数作为路由的返回值时是否会出现这种情况?
调用“重定向”函数作为路由的返回值时是否会出现这种情况?
不可以。flask 重定向以 HTTP 重定向响应,然后工作人员可以自由地接受新请求。 客户端在看到此响应时发出另一个请求,并且每当工作人员准备好时都会收到此请求。
我通过向 gnuicorn 添加额外的工人来解决这个问题:
web: gunicorn --workers=3 BlocAPI:app --log-file -
不知道为什么。
这与@anilpai之前在他设置workers=1 + (multiprocessing.cpu_count() * 2)
.. 的评论中有关吗?
我有一个类似的问题。 原来我的应用程序入口点有错误。 从调试来看,我基本上是从 gunicorn 启动一个烧瓶应用程序,其工作人员随后进入一个无限连接循环,每 30 秒超时一次。
我确信这不会影响上述所有用户,但可能会影响某些用户。
在我用gunicorn module.wsgi
运行的module/wsgi.py
文件中,我有 -
application = my_create_app_function()
application.run(host="0.0.0.0")
而我应该有 -
application = my_create_app_function()
if __name__ == "__main__":
application.run(host="0.0.0.0")
本质上,您不想在使用 gunicorn 时调用application.run()
。 gunicorn 下的__name__
不会是"__main__"
,但在 Flask 中会,所以你仍然可以在本地调试。
我在 gunicorn 文档中找不到对此的引用,但可以想象这是一个常见的错误案例,所以也许需要一些警告。
这种情况仍在发生。 在 Gunicorn 调用中添加--preload
为我解决了这个问题。
这个bug还没有修复吗? 我正在观察这种确切的行为。
Gunicorn 在 systemd 中是这样启动的:
[Service]
PIDFile = /run/gunicorn.pid
WorkingDirectory = /home/pi/pyTest
ExecStart=/usr/local/bin/gunicorn app:app -b 0.0.0.0:80 --pid /run/gunicorn.pid
RuntimeDirectory=/home/pi/pyTest
Restart=always
KillSignal=SIGQUIT
Type=notify
StandardError=syslog
NotifyAccess=all
User=root
Group=root
ExecReload = /bin/kill -s HUP $MAINPID
ExecStop = /bin/kill -s TERM $MAINPID
ExecStopPost = /bin/rm -rf /run/gunicorn
PrivateTmp = true
工作进程不断超时并重新启动:
Jul 10 15:19:20 raspberryVM gunicorn[10941]: [2020-07-10 15:19:20 -0700] [10941] [CRITICAL] WORKER TIMEOUT (pid:10944)
Jul 10 15:19:20 raspberryVM gunicorn[10941]: [2020-07-10 15:19:20 -0700] [10944] [INFO] Worker exiting (pid: 10944)
Jul 10 15:20:15 raspberryVM gunicorn[10941]: [2020-07-10 15:20:15 -0700] [10985] [INFO] Booting worker with pid: 10985
app.py 是一个简单的 Flask 应用程序。
这个问题是否因为不修复而关闭?
我也遇到了同样的问题
但是在调试之后,我发现当 gunicorn 启动 Django App 时,其中一个依赖项花费的时间比预期的要长,(在我的情况下是外部数据库连接),这使得gunicron
工人超时
当我解决了连接问题时,超时问题也解决了......
这不是我的情况。 我使用“Hello, World”类型的应用程序进行了测试,没有依赖项。 所以我仍然对此感到困惑,但似乎不可能让 Gunicorn 具有长时间运行的线程。 工作进程重新启动并因此终止长时间运行的线程。
@leonbrag
这可能不是 gunicorn 错误。 在线程中查看我上面的推荐。 这是浏览器发送空的“预测的”TCP 连接,并在没有空 TCP 连接保护的情况下仅使用少数同步工作线程运行 gunicorn 的副作用。
是否有参考架构/设计显示了使用长(永久)工作线程设置 Gunicorn 烧瓶应用程序的正确方法?
如果这不是错误,那么它似乎是 Gunicorn 架构/设计的人工制品或限制。
为什么不同步工作者永远运行并接受客户端连接。 这样的工作者会根据需要关闭套接字,但继续运行而不退出(因此工作线程继续运行)。
@leonbrag
您应该更具体地说明您要解决的问题。
此线程中讨论的问题发生在开发环境中,最简单的解决方案是添加更多同步工作线程或使用线程工作线程。
如果你想在生产设置中避免这个问题,你可以使用 gevent worker,或者你可以在 gunicorn 前面放置一个 nginx。
一些PaaS已经在你的docker容器前面放了一个nginx,所以你不必担心。 同样,解决方案取决于上下文和细节。
您可以从文档中查看设计页面。 异步工作者是其中之一
运行长任务的方法。
在星期六2020年8月8日18:00 leonbrag [email protected]写道:
是否有参考架构/设计显示了正确的设置方式
具有长(永久)工作线程的 Gunicorn 烧瓶应用程序?如果这不是错误,那么它似乎是工件或限制
Gunicorn 架构/设计。为什么不同步工作者永远运行并接受客户端连接。 这样的
worker 会根据需要关闭套接字,但继续运行而不退出
(因此工作线程继续运行)。—
你收到这个是因为你被提到了。
直接回复本邮件,在GitHub上查看
https://github.com/benoitc/gunicorn/issues/1801#issuecomment-670944797 ,
或取消订阅
https://github.com/notifications/unsubscribe-auth/AAADRIWRQGIP3R5PMVJ5ENTR7VZA3ANCNFSM4FDLD5PA
.>
从我的手机发送
网络:gunicorn --workers=3 app:app --timeout 200 --log-file -
我通过增加 --timeout 解决了我的问题
有关 Docker 相关的 tmpfs 问题,另请参阅 #1388。
哦,非常感谢 Randall,我在 Docker 中运行 gunicorn 时忘记将--worker-tmp-dir /dev/shm
到 gunicorn 参数中。
顺便说一句,64 Mb 是否足以用于 gunicorn 缓存?
奇怪的是,我添加了--worker-tmp-dir /dev/shm
但仍然收到:
[2020-11-27 21:01:42 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:17)
为了确保/dev/shm
是 ramfs,我对其进行了基准测试:
参数是下一个:
command: /bin/bash -c "cd /code/ && pipenv run gunicorn --worker-tmp-dir /dev/shm conf.wsgi:application --bind 0.0.0.0:8022 --workers 5 --worker-connections=1000"
PS:我正在使用 PyPy
@attajutt超时很好,但是您冒着风险,gunicorn 主进程只会在 1000 秒后检测到您的工作进程中的挂断,并且您将错过很多请求。 如果只有几个工人中的一个挂断电话,也很难检测到它。 我至少不会做 1000。
@ivictbor感谢
为找到此线程的人添加另一种可能性...
这也可能是由于 docker 强加的资源限制对于您的 Web 应用程序来说太低了。 例如,我有以下限制:
services:
web_app:
image: blah-blah
deploy:
resources:
limits:
cpus: "0.25"
memory: 128M
这些对于gunicorn
显然太低[CRITICAL] WORKER TIMEOUT
错误,直到我删除了约束。
对于 gunicorn 来说,这个资源非常好。 但你确实需要
飞机的工人数量和您所需的资源
应用。 128M 和 0.25cpu 对于 Web 应用程序来说似乎真的很低
用 Python 编写.... 一般来说,您至少需要 1 个核心 /vcpu 和
至少 512MB 的 RAM。
2021 年 3 月 26 日星期五 02:14,科尔顿·希克斯@ 。 * > 写道:
为找到此线程的人添加另一种可能性...
这也可能是由于 docker 强加了资源限制导致的
对您的 Web 应用程序来说太低了。 例如我有以下内容
约束:服务:
网络应用程序:
图片:胡说八道
部署:
资源:
限制:
处理器:“0.25”
内存:128M这些对于 gunicorn 来说显然太低了所以我不断得到 [CRITICAL]
WORKER TIMEOUT 错误,直到我删除了约束。—
你收到这个是因为你被提到了。
直接回复本邮件,在GitHub上查看
https://github.com/benoitc/gunicorn/issues/1801#issuecomment-807855647 ,
或取消订阅
https://github.com/notifications/unsubscribe-auth/AAADRITPZB7BMA6QW7LFNVLTFPNV3ANCNFSM4FDLD5PA
.>
从我的手机发送
--timeout=1000 对我有用。 问题是低 CPU 资源的 GCP 机器。 它在我的本地机器上运行良好,默认超时。
最有用的评论
将 gunicorn 与 gevent 一起使用并没有修复该错误。