Gunicorn: Flaskアプリを実行しているときの重要なワーカーのタイムアウト

作成日 2018年06月05日  ·  82コメント  ·  ソース: benoitc/gunicorn

[CRITICAL] WORKER TIMEOUTエラーに関連するレポートがすでにいくつかあるようですが、ポップアップし続けます。 これが私の問題です。

このFlaskhelloworldアプリケーションを実行しています。

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

エラーが発生する理由と、この例で予期されているかどうかを明確に説明していただけますか? どうすれば修正できますか、それとも予想される動作である場合は、なぜ重大なエラーが発生するのでしょうか。

Investigation unconfirmed

最も参考になるコメント

geventでgunicornを使用しても、バグは修正されませんでした。

全てのコメント82件

エラーは予期されていませんが、エラーが発生する理由を示す例はありません。 あなたの環境について詳しく教えてください。

  • Gunicornへの接続に使用されるクライアントは何ですか?
  • Gunicornへの接続に使用されるリバースプロキシはありますか?

あなたの環境について詳しく教えてください。

  • Gunicornへの接続に使用されるクライアントは何ですか?
    => Chromiumからリクエストを送信します: http:// localhost :5000 /
  • Gunicornへの接続に使用されるリバースプロキシはありますか?
    =>プロキシなし、Gunicorn + Flaskのみ

完全に新しいセットアップで問題を再現しました。手順は次のとおりです。

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デフォルトのタイムアウトが原因だと思いますが、ワーカーは30http://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ワーカーを使用してみてください。これを解決できます。

その意味で、クリティカルレベルのログは非常に紛らわしいものです。

まさに、それが私の最初の質問でした。それが予想される動作である場合、なぜ重大なエラーが発生するのでしょうか。
ワーカーを再起動する必要がある理由についての背景を知ることもできます。おそらく、これを設計ドキュメントに追加することができます。

私もこれを見て( examples/test.pygunicorn 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は、ドキュメントを改善して、そのようなエラーに対するより多くのユースケースと応答を提供する必要があります。

ワーカーがビジー状態になっていないときにエラーが引き続き発生する場合は、他に何かが発生しており、おそらくバグがあります。

[編集]
私にとっても同じバグです。
python2.7のDjango1.10 / gunicorn 19.6.0 / Python 2.7.15-Debian8.8のalpineとストックカーネル3.16では、すべて正常に機能していました。
Django1.11とgunicorn19.8.1にアップデートした後、ワーカーは[CRITICAL WORKERTIMEOUT]で起動に失敗し続けます。
gunicornを19.6.0にダウングレードしても、問題は解決しません。
ホストカーネルを4.9.0に更新し(スケジュールされていました)、ワーカーはエラーなしで正常に起動しました。
しかし:

  • 4人の労働者を使用します
  • Djangoアプリを正確に4回呼び出した後、次の呼び出しはタイムアウトになり、ログに[CRITICAL WORKERTIMEOUT]が表示されます
  • linux topコマンドは、4つのgunicornプロセスがかなり高いCPU消費でスタックしていることを示しています。

gunicorn geventを試して、アプリをオンラインに戻すことができるかどうかを確認します。

geventでgunicornを使用しても、バグは修正されませんでした。

この問題に関する更新はありますか?

@neocolorがMSYSで実際のバグを特定したよう

@bigunyakどのプラットフォームで実行していますか? 簡単な例で再現しようとしましたが、上記の手順を正確に実行することはできません。 これは、複数のフレームワークで本番環境で複数のアプリケーションを実行した私の経験と一致しています。 私の知る限り、労働者の通知システムは最近変わっていません。 私のプラットフォームはMacOS10.13.6のPython3.7ですが、Python 2.7および3.6.5のいくつかのアプリケーションの同期ワーカーを使用してGunicornを本番環境で実行し、ワーカーをブロックする正当に長いリクエストがある場合にのみワーカーのタイムアウトが表示されます。

@Tberdyの場合: --worker-tmp-dirをtmpfsファイルシステムの外部に設定しようとするとどうなりますか? アルパインやドッカー、あるいはその組み合わせが、労働者がアービターに通知する方法を何らかの形で妨害するのではないかと思っています。

Docker関連のtmpfsの問題については、#1388も参照してください。

私はこの問題を抱えています。

私にもこの問題があります。gunicornsyncは昨夜まで完全に機能していました。レポートを開始し、geventを使用したワーカーのタイムアウト[CRITICAL]で問題が解決したようですが、なぜこれが発生したのかを知りたいと思います。

@ timoj58 @cjmashこの問題について詳しく

@benoitc kubernetesでDjangoプロジェクトを開始するためにgunicornを実行しています。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でワーカーを起動しています:13

E [2018-08-09 21:47:56 +0000] [14] [INFO] pidを使用した起動ワーカー:14

E [2018-08-09 21:47:56 +0000] [12] [INFO] pidを使用した起動ワーカー: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を使用した起動ワーカー:9

E [2018-08-09 21:47:55 +0000] [8] [INFO] pidを使用した起動ワーカー:8

E [2018-08-09 21:47:55 +0000] [1] [情報]ワーカーの使用:同期

E [2018-08-09 21:47:55 +0000] [1] [INFO]リスニング: http

E [2018-08-09 21:47:55 +0000] [1] [DEBUG]アービターが起動しました

E [2018-08-09 21:47:55 +0000] [1] [INFO] gunicorn19.7.1を開始しています

E raw_paste_global_conf:[]

E暗号:TLSv1

E do_handshake_on_connect:False

Esuppress_ragged_eofs:True

E ca_certs:なし

E cert_reqs:0

E ssl_version:2

E certfile:なし

Eキーファイル:なし

E proxy_allow_ips:['127.0.0.1']

E proxy_protocol:False

E on_exit:

E nworkers_changed:

E worker_exit:

E child_exit:

E post_request:

E pre_request:

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:False

E syslog_facility:user

E syslog_prefix:なし

E syslog:False

E syslog_addr: udp:// localhost :514

E logconfig:なし

E logger_class:gunicorn.glogging.Logger

E Capture_output:False

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:False

E umask:0

Eグループ:0

Eユーザー:0

E worker_tmp_dir:なし

E pidfile:なし

E raw_env:[]

Eデーモン:False

E chdir:/ usr / src / app

E sendfile:なし

E preload_app:False

E check_config:False

E spew:False

E reload_engine:auto

Eリロード:False

E limit_request_field_size:8190

E limit_request_fields:100

E limit_request_line:4094

Eキープアライブ:2

E graceful_timeout:30

Eタイムアウト:1200

E max_requests_jitter:0

E max_requests: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]現在の構成:

適用する移行はありません。

移行を実行しています:

すべての移行を適用します: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:/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を使用した起動ワーカー:12

E [2018-08-09 21:46:34 +0000] [13] [INFO] pidを使用した起動ワーカー: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を使用した起動ワーカー:9

E [2018-08-09 21:46:34 +0000] [8] [INFO] pidを使用した起動ワーカー:8

E [2018-08-09 21:46:34 +0000] [7] [INFO] pidを使用した起動ワーカー:7

E [2018-08-09 21:46:34 +0000] [1] [情報]ワーカーの使用:同期

E [2018-08-09 21:46:34 +0000] [1] [INFO]リスニング: http

E [2018-08-09 21:46:34 +0000] [1] [DEBUG]アービターが起動しました

E [2018-08-09 21:46:34 +0000] [1] [INFO] gunicorn19.7.1を開始しています

E raw_paste_global_conf:[]

E暗号:TLSv1

E do_handshake_on_connect:False

Esuppress_ragged_eofs:True

E ca_certs:なし

E cert_reqs:0

E ssl_version:2

E certfile:なし

Eキーファイル:なし

E proxy_allow_ips:['127.0.0.1']

E proxy_protocol:False

E on_exit:

E nworkers_changed:

E worker_exit:

E child_exit:

E post_request:

E pre_request:

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:False

E syslog_facility:user

E syslog_prefix:なし

E syslog:False

E syslog_addr: udp:// localhost :514

E logconfig:なし

E logger_class:gunicorn.glogging.Logger

E Capture_output:False

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:False

E umask:0

Eグループ:0

Eユーザー:0

E worker_tmp_dir:なし

E pidfile:なし

E raw_env:[]

Eデーモン:False

E chdir:/ usr / src / app

E sendfile:なし

E preload_app:False

E check_config:False

E spew:False

E reload_engine:auto

Eリロード:False

E limit_request_field_size:8190

E limit_request_fields:100

E limit_request_line:4094

Eキープアライブ:2

E graceful_timeout:30

Eタイムアウト:1200

E max_requests_jitter:0

E max_requests: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にはまだ残っています。
それを再現する手順は、この投稿で説明したものとまったく同じです。
私のシステムはArchLinux x86_64 GNU / Linux(カーネル4.17.2-1-ARCH)、Python3.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の内容です。

  • Pipfile
[[source]]
url = "https://pypi.org/simple"
verify_ssl = true
name = "pypi"

[packages]
flask = "*"
gunicorn = "*"

[dev-packages]

[requires]
python_version = "3.6"
  • Pipfile.lock
{
    "_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()

私に試してもらいたい/実験してほしいことがあるかどうか、またはログに確認してほしい詳細があるかどうかを知らせてください。 GCPVMでflaskを実行しています。

返事が遅れて申し訳ありません。 私はそれを実行しています

gunicorn --log-file = / home / ubuntu / log / gunicorn.logpredictor_api :app -b localhost:5000

gevent設定などを使用しましたが、問題を回避するために必要なものの設計を変更したため、上記の基本設定(これも失敗しましたが、geventがない場合は予想されます)

Pythonバージョン3.6
env:aws tensorflow_p36 optmized(ubuntu)
nginxは、フラスコアプリを実行しているgunicornの前に座っています。

フラスコバージョン1.0.2
nginxバージョン1.10.3
gunicornバージョン19.9.0

これが原因である可能性がある場合に備えて、nginxタイムアウトも変更しました。

gunicornサーバーで同じ問題に直面している

#gunicornアプリケーションionServer:app -b 0.0.0.0:6001 -w 8 --threads 4 --backlog 2048 \
#-timeout 120 --graceful-timeout 60 --access-logfile logs / access.log \

--error-logfile logs / error.log --log-level = info

フラスコ== 0.12.1
gunicorn == 19.7.1

上記のコマンドでサーバーを起動すると、システムがしばらくフリーズし、ワーカーpidが起動し続けますが、タイムアウトを120秒保持し、サーバーは単一の要求を受け入れていません。

この問題に関する更新はありますか? 私は同じ問題を抱えています

[重要]ワーカータイムアウト

誰かがDockerイメージでこれをうまく再現したかどうか疑問に思っていますか?

また、gunicorn -k gevent --threads4で始まる既存のアプリケーションにdatadogのddtrace-runワーカーを実装しようとしたときにもこれが表示されます。

私も今まで見たことがない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 ElasticBeanstalkで単一のDockerコンテナを使用してDjangoを実行するとこの問題が発生しました。 セキュリティグループを修正して、EC2インスタンスがRDSインスタンスと通信できるようにすることで、この問題を解決しました。 これはこの問題に関する99%の人々の解決策ではないかもしれないことを認識していますが、他の人がこのウサギの穴に落ちる時間を無駄にしないように、このメモを残しています。

私の場合、問題はsystemctl daemon-reload実行することで解決されました。
簡単に言うと、デフォルトのタイムアウトが30秒であることは知っていましたが、サービスに変更を適用するには、もちろんsystemdデーモンをリロードする必要があると判断するまで変更できませんでした。

@bigunyak @benoitc @tilgovi
長いグーグルガチョウの追跡といくつかの実験の後、この問題の根本的な原因は、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で単一の同期ワーカーのみを実行している場合に発生する可能性が高くなります。 しかし、私の実験でわかったように、複数の同期ワーカーを実行している場合でも発生する可能性があります。

私の環境

  • 私のネイティブOSはUbuntu17です
  • ローカルのDockerコンテナでRESTAPIを実行しています。 Dockefileからの関連行
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
......
  • Firefox 61.0.1、Chromium 67.0.3396.99、Chrome70.0.3538.102の3つのブラウザをインストールしています。
  • 別のポートの別のDockerコンテナから提供されるReactアプリがあります
  • reactアプリは私のAPIにCORSAJAXリクエストを作成します(JavaScriptが1つのローカルホストポートで提供され、API呼び出しを別のローカルホストポートに送信するため、これらはCORSリクエストです)
  • 私の実験で常に「ブロック」されるリクエストは、CORS OPTIONSリクエストです(ブラウザによってトリガーされ、POSTリクエストを実行する許可を求めます)。 POST呼び出しでフォローアップする可能性が高いため、ブラウザーがOPTIONS呼び出しで予測接続を確立しようとするのは論理的であるように思われます。

実験1
Gunicornの設定:1つの同期ワーカー(デフォルトは30秒のタイムアウト)

Firefox:ほぼすべてのreactページの読み込みで、CORS OPTIONSリクエストは5秒間ブロックされ、その後成功します。
Chromium:すべての反応ページの読み込み時に、CORSOPTIONSリクエストは1.5分間ブロックされます!!!! そして成功します。
Chromium(予測サービスが無効):すべてが正常に読み込まれます
Chrome:すべてが正常に読み込まれます

実験2
Gunicornの設定:4つの同期ワーカー(デフォルトは30秒のタイムアウト)

Firefox:すべてが正常に読み込まれます
Chromium:3回目のreactページの読み込みごとに、CORS OPTIONSリクエストは30秒間ブロックされ、その後成功します。
Chromium(予測サービスが無効):すべてが正常に読み込まれます
Chrome:すべてが正常に読み込まれます

実験3
Gunicornの設定:8つの同期ワーカー(デフォルトは30秒のタイムアウト)

Firefox:すべてが正常に読み込まれます
クロム:すべてが正常にロードされます
Chrome:すべてが正常に読み込まれます

実験4
threaded=True flask開発サーバーを実行します

Firefox:すべてが正常に読み込まれます
クロム:すべてが正常にロードされます
Chrome:すべてが正常に読み込まれます

実験のまとめ

  • Firefoxにも予測サービスがあるようですが、もっと優雅なようです。 (実験1)
  • Chromiumは、「予測」接続の作成において最も積極的なようです。 OPTIONSリクエスト中に最大3〜4個の「予測」接続を起動するようです(実験1および2)
  • 驚いたことに、Chromeでは予測サービスも有効になっていますが、どの実験でも問題は発生しませんでした(「予測」接続の順序や数はChromiumとは異なる可能性があります)

解決
本番環境で:最も簡単な修正は、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は、シングルスレッドサーバーで同様の症状を引き起こす低速クライアントのもう1つの珍しいケースです。この場合、非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)

うまくいけば、これはあなたのアプリがどこにぶら下がっているのかを明らかにするはずです。

たとえば、私はどういうわけかgevent.monkey.patch_all() import flask前にapp._before_request_lockは最終的に非イベントロックになりました(つまり、パッチが適用されていないthreading.Lock )。 このような場合、アプリの起動時に2つのリクエストが連続して発生すると、アプリがハングします(2番目のリクエストはスレッド全体をロックします)。 しかし、これは私のバグであり、あなたのバグは異なる場合があります。

@asnisarenkoなぜハングアップしているのかread()が送信されると、グリーンレットをブロックすることを意味しますが、 readはモンキーパッチを適用する必要があるため、他のグリーンレット。

@ikonst
この問題は、デフォルト設定でgunicornを実行することについて話している。 デフォルトのワーカークラスはsync http://docs.gunicorn.org/en/stable/settings.html#worker -class

syncワーカーはプリフォークモデルを使用し、各ワーカーは一度に1つの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は、私たちの間であまり知識がない

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 、何も変わりませんでした。

私はWindows10Proを使用しています。 DockerComposeを使用
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秒以内に送信される限り接続を維持することになっていますが、gunicornは、まだ実行されてデータを生成しているにもかかわらず、30秒以内に終了しなかった場合、プロセスを強制終了するようです。

この点に関して、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)を挿入しましたが、実際に機能しました(その時点で機能しなかった理由はわかりません)。私は質問を投稿しました)。

--timeout = 5

これがこの問題の最も一般的な原因です。

私の解決策があなたのお役に立てば幸いです。 私は数日前にこの重大なワーカータイムアウトの問題に遭遇し、いくつかの解決策を試しました。 今ではうまく機能します。

これが私の理解と解決策です:

  1. gunicornでプリロードしてみてください

サービスを開始するためにテンソルフローバックエンドなどのパッケージをロードするためにより多くの時間が必要なため、ワーカーの起動に失敗します。 そのため、アプリの起動時間が遅い場合は、gunicornでプリロードオプションを有効にしてみてください(https://devcenter.heroku.com/articles/python-gunicorn#advanced-configurationを参照)。

gunicorn hello:app --preload

  1. gunicornのタイムアウトを増やしてみてください

デフォルトのタイムアウトは30秒です。 アプリケーションがAPIを完了するのに本当に多くの時間を必要とする場合は、タイムアウトを増やしてください。

gunicorn hello:app --timeout 10

ただし、私の観点からは、APIが終了するのに1分以上かかる場合は意味がありません。 もしそうなら、あなたのコードでいくらかの進歩を遂げるようにしてください。

  1. k8sを使用している場合は、yamlでコンテナ/イメージのtimeoutSecondsを設定することもできます。

今日も同じ問題に直面しました。 私の場合、APIがデータを計算してクライアントに戻るのに約1分かかっていたため、CRITICAL WORKERTIMEOUTエラーが発生しました。 gunicornのタイムアウトフラグを1分以上に増やすことで解決しました。問題は解決しましたが、問題が再発することはありませんでした。 お役に立てれば。 私はuvicorn.workers.UvicornWorkerを使用しています。

gnuicornにワーカーを追加して、これを修正しました。

web: gunicorn --workers=3 BlocAPI:app --log-file -

理由はわかりません。

多分あなたは行き​​詰まりを持っていましたか? アプリはそれ自体にリクエストを送信しますか?

2020年1月5日、日曜日、10:52 alpinechicken、 notifications @ github.comは次のように書いています。

gnuicornにワーカーを追加して、これを修正しました。

web:gunicorn --workers = 3 BlocAPI:app -- file-

理由はわかりません。


コメントしたのでこれを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/benoitc/gunicorn/issues/1801?email_source=notifications&email_token=AAAEQJVQRCW3C63EZJWIN5DQ4G3WTA5CNFSM4FDLD5PKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN
または購読を解除する
https://github.com/notifications/unsubscribe-auth/AAAEQJXZM4NLK56DZMFSZALQ4G3WTANCNFSM4FDLD5PA

うん、あるルートが別のルートを呼び出す-それは悪いですか?

これは、少なくとも2人のワーカーが必要であることを意味します。そうでない場合、サーバーは
デッドロック。 リクエストは、サーバーが2番目に応答するまで待機します
リクエスト(キューに入れられます)。

ワーカーごとに1つの同時リクエストを受け取ります。

2020年1月6日月曜日、02:45 alpinechicken、 notifications @ github.comは次のように書いています。

うん、あるルートが別のルートを呼び出す-それは悪いですか?


コメントしたのでこれを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/benoitc/gunicorn/issues/1801?email_source=notifications&email_token=AAAEQJSFEFBBI6AMZJCM4C3Q4KLOJA5CNFSM4FDLD5PKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW
または購読を解除する
https://github.com/notifications/unsubscribe-auth/AAAEQJXTCPOFIZJU5PUPOODQ4KLOJANCNFSM4FDLD5PA

ああ、それは理にかなっています。 ありがとう!

火、2020年1月7日には6:23でbobf [email protected]書きました:

これは、少なくとも2人のワーカーが必要であることを意味します。そうでない場合、サーバーは
デッドロック。 リクエストは、サーバーが2番目に応答するまで待機します
リクエスト(キューに入れられます)。

ワーカーごとに1つの同時リクエストを受け取ります。

2020年1月6日月曜日、02:45 alpinechicken、 notifications @ github.comは次のように書いています。

うん、あるルートが別のルートを呼び出す-それは悪いですか?


コメントしたのでこれを受け取っています。
このメールに直接返信し、GitHubで表示してください
<<
https://github.com/benoitc/gunicorn/issues/1801?email_source=notifications&email_token=AAAEQJSFEFBBI6AMZJCM4C3Q4KLOJA5CNFSM4FDLD5PKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW

または購読を解除する
<<
https://github.com/notifications/unsubscribe-auth/AAAEQJXTCPOFIZJU5PUPOODQ4KLOJANCNFSM4FDLD5PA


コメントしたのでこれを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/benoitc/gunicorn/issues/1801?email_source=notifications&email_token=AAH2WRPVPVO2EJ53BKQW5B3Q4OHLRA5CNFSM4FDLD5PKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW
または購読を解除する
https://github.com/notifications/unsubscribe-auth/AAH2WRM2LLIB4O6OHCU5UG3Q4OHLRANCNFSM4FDLD5PA

worker_class '、' sync ')

ワーカー数とスレッド数を一致させることで、この問題を解決できます。

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のドキュメントによると、複数のスレッドが言及されている場合は、ワーカークラスがsyncからgthreadに変更されます。
PS:-
同期ワーカータイプを使用してスレッド設定を1より大きい値に設定しようとすると、代わりにgthreadワーカータイプが使用されます。

私の場合:

環境:Ubuntu18.04 + gunicorn + nginx + flask

私の仮想環境にpipinstall gunicorn [gevent]

gunicorn -b localhost:8000 -w 4 web:appgunicorn -b localhost:8000 -k gevent web:app

できます。

お互いに問題を解決するために多くのことをしてくれたここにいるすべての人に感謝します。 適切と思われる場合は、引き続きこの問題に投稿してください。

ただし、ここでGunicornにバグはないと思い、実行するアクションはないと思うので、この問題を閉じます。ただし、この問題のドキュメントを追加または改善しようとするPRのレビューを喜んでお手伝いします。メッセージをログに記録します。

私の意図を誤解しないでください。 Gunicornのバグが疑われ、引き続き議論したい場合は、そうしてください。 できれば、問題を再現するサンプルアプリケーションを使用して新しいチケットを開きます。 ただし、現時点では、この問題にはさまざまな問題、解決策、会話が多すぎて、非常に読みやすくなっています。

バッファリングリバースプロキシを前に配置せずにGunicornを実行すると、さまざまな理由でデフォルトの同期ワーカーでタイムアウトが発生します。 一般的なものは次のとおりです。

  • 遅いクライアント
  • ブラウザとプロキシによって開いたままになっている接続のプリコネクト/プリフェッチ
  • 外部APIを呼び出すか、CPUにバインドされた多くの作業を行うため、応答が長くなります

非同期またはスレッドワーカータイプに切り替えるか、Gunicornをバッファリングリバースプロキシの背後に配置することができます。 タイムアウトの原因が、独自のコードが外部APIをゆっくりと呼び出したり、期待どおりの重要な作業を行ったりしていることがわかっている場合は、 --timeoutオプションを増やすことができます。

これは、少なくとも2人のワーカーが必要であることを意味します。そうしないと、サーバーがデッドロックします。 要求は、サーバーが2番目の要求(キューに入れられる)に応答するまで待機します。 ワーカーごとに1つの同時リクエストを受け取ります。

2020年1月6日月曜日、02:45 alpinechicken、 @* >書いた:うん、あるルートが別のルートを呼び出す-それは悪いですか?

これは、ルートの戻り値として「リダイレクト」関数を呼び出す場合に当てはまりますか?

これは、ルートの戻り値として「リダイレクト」関数を呼び出す場合に当てはまりますか?

いいえ。フラスコリダイレクトはHTTPリダイレクトで応答し、ワーカーは新しいリクエストを自由に受け入れることができます。 クライアントは、この応答を確認したときに別の要求を行い、ワーカーの準備ができているときはいつでもこの要求を受け取ります。

gnuicornにワーカーを追加して、これを修正しました。

web: gunicorn --workers=3 BlocAPI:app --log-file -

理由はわかりません。

これは、彼がworkers=1 + (multiprocessing.cpu_count() * 2)を設定した以前の@anilpaiコメントに関連していますか?

私はこれと同様の問題を抱えていました。 アプリケーションへのエントリポイントでエラーが発生したことが判明しました。 デバッグから、私は基本的にgunicornからflaskアプリを起動しているように見えました。その後、そのワーカーは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を追加すると、問題が修正されました。

このバグはまだ修正されていませんか? 私はこの正確な振る舞いを観察しています。

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を起動しているときに、依存関係の1つが予想よりも長くかかっていたことがわかりました(私の場合は外部DB接続)。これにより、 gunicronワーカーがタイムアウトします。

接続の問題を解決すると、タイムアウトの問題も解決しました...

これは私の場合ではありません。 依存関係のない「Hello、World」タイプのアプリでテストしました。 だから私はまだこれに戸惑っていますが、Gunicornを長時間実行するスレッドを持つことは不可能のようです。 ワーカープロセスが再起動するため、長時間実行されているスレッドが強制終了されます。

@leonbrag
これはおそらくgunicornのバグではありません。 上記のスレッドで私の表彰を参照してください。 これは、ブラウザが空の「予測された」TCP接続を送信し、空のTCP接続から保護せずに少数の同期ワーカーのみでgunicornを実行することの副作用です。

長い(永続的な)ワーカースレッドでGunicornフラスコアプリをセットアップする適切な方法を示すリファレンスアーキテクチャ/デザインはありますか?

これがバグではない場合は、Gunicornのアーキテクチャ/設計のアーティファクトまたは制限のようです。

ワーカーの実行を永久に同期してクライアント接続を受け入れないのはなぜですか。 このようなワーカーは、必要に応じてソケットを閉じますが、終了せずに実行を継続します(したがって、ワーカースレッドは実行を継続します)。

@leonbrag
解決しようとしている問題について、より具体的にする必要があります。

このスレッドで説明されている問題は開発環境で発生します。最も簡単な解決策は、同期ワーカーを追加するか、スレッドワーカーを使用することです。

本番環境でこの問題を回避したい場合は、geventワーカーを使用するか、nginxをgunicornの前に配置することができます。
一部のPaaSは、Dockerコンテナの前にすでにnginxを配置しているため、心配する必要はありません。 この場合も、解決策はコンテキストと詳細によって異なります。

これは良い読み物です。
https://www.brianstorti.com/the-role-of-a-reverse-proxy-to-protect-your-application-against-slow-clients/

ドキュメントからデザインページを確認できます。 非同期ワーカーは1つです
長いタスクを実行する方法。

土2020年8月8日の18:00にleonbragの[email protected]書きました:

セットアップの適切な方法を示すリファレンスアーキテクチャ/設計はありますか
長い(永続的な)ワーカースレッドを備えたGunicornフラスコアプリ?

これがバグではない場合は、アーティファクトまたは制限のようです。
Gunicornのアーキテクチャ/デザイン。

ワーカーの実行を永久に同期してクライアント接続を受け入れないのはなぜですか。 そのような
ワーカーは必要に応じてソケットを閉じますが、exItingなしで実行を継続します
(したがって、ワーカースレッドは引き続き実行されます)。


あなたが言及されたので、あなたはこれを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/benoitc/gunicorn/issues/1801#issuecomment-670944797
または購読を解除する
https://github.com/notifications/unsubscribe-auth/AAADRIWRQGIP3R5PMVJ5ENTR7VZA3ANCNFSM4FDLD5PA

>>

私の携帯から送信

web:gunicorn --workers = 3 app:app --timeout 200 --log-file-

--timeoutを増やすことで問題を修正しました

Docker関連のtmpfsの問題については、#1388も参照してください。

ああ、Randallに感謝します。Dockerでgunicornを実行しているときに、gunicornの引数に--worker-tmp-dir /dev/shmを追加するのを忘れました。

ところで、gunicornのキャッシュには64 Mbで十分ですか?

gunicorn app:app --timeout 1000
または
gunicorn app:app --preload

私のために働いた...私はタイムアウト1を好む。

奇妙なことに、私は--worker-tmp-dir /dev/shmを追加しましたが、それでも受け取ります:

[2020-11-27 21:01:42 +0000] [1] [CRITICAL] WORKER TIMEOUT (pid:17)

/dev/shmがramfsであることを確認するために、ベンチマークを行いました。

image

次のパラメータは次のとおりです。

    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秒後にのみワーカープロセスのハングアップを検出するリスクがあり、多くのリクエストを見逃してしまいます。 また、数人の労働者のうち1人だけが電話を切ると、それを検出するのは困難になります。 私は少なくとも1000はしません。

@ivictborlmkに感謝します。 1000は参考用です。 それにもかかわらず、ロードされたアプリは完全に正常に実行されています。

私もこのエラーの問題が発生し、数回後、問題がおそらく引き起こされていることがわかりました:

  1. Nginx構成
  2. Gunicorn / Uwsgi

GAEのようなクラウドにアプリをデプロイする場合、ヒントエラーは発生しません。
このケースソリューションを使用してエラーを表面化することができます: https

502の不良ゲートウェイを発生させた場合。
おそらく2つの可能性があります:

  1. gunicornが実行されていません
  2. gunicornがタイムアウトになりました

ここで説明されている完全なsulotion: https ://www.datadoghq.com/blog/nginx-502-bad-gateway-errors-gunicorn/

[CRITICAL] WORKERTIMEOUTでエラーが発生した人を修正できることを願っています

このスレッドを見つけた人のために別の可能性を追加しています...

これは、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、Colton Hicks @* >書いた:

このスレッドを見つけた人のために別の可能性を追加しています...

これは、Dockerがリソースの制約を課していることによっても発生する可能性があります。
Webアプリケーションには低すぎます。 たとえば、私は次のようになりました
制約:

サービス:
web_app:
画像:何とか何とか
配備:
資力:
制限:
CPU:「0.25」
メモリ:128M

そして、これらは明らかにgunicornには低すぎたので、私は常に[CRITICAL]を入手しました。
制約を削除するまで、WORKERTIMEOUTエラーが発生しました。


あなたが言及されたので、あなたはこれを受け取っています。
このメールに直接返信し、GitHubで表示してください
https://github.com/benoitc/gunicorn/issues/1801#issuecomment-807855647
または購読を解除する
https://github.com/notifications/unsubscribe-auth/AAADRITPZB7BMA6QW7LFNVLTFPNV3ANCNFSM4FDLD5PA

>>

私の携帯から送信

--timeout = 1000は私から働きました。 問題は、低CPUリソースのGCPマシンでした。 デフォルトのタイムアウトでローカルマシンで正常に動作しました。

このページは役に立ちましたか?
0 / 5 - 0 評価