Gunicorn: CRITICAL WORKER TIMEOUT beim Ausführen der Flask-App

Erstellt am 5. Juni 2018  ·  82Kommentare  ·  Quelle: benoitc/gunicorn

Es scheint, dass es bereits mehrere Berichte zu dem Fehler [CRITICAL] WORKER TIMEOUT , aber er taucht immer wieder auf. Hier ist mein Problem.

Ich betreibe diese Flask Hello World-Anwendung.

from flask import Flask
application = Flask(__name__)

@application.route('/')
def hello_world():
    return 'Hello, World!'

Der Gunicorn-Befehl ist dieser:

gunicorn -b 0.0.0.0:5000 --log-level=debug hello

Und das ist die Konsolenausgabe:

[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

Können Sie bitte klar erklären, warum ich den Fehler erhalte und ob er in diesem Beispiel erwartet wird? Wie behebe ich es oder wenn es ein erwartetes Verhalten ist, warum dann ein kritischer Fehler?

Investigation unconfirmed

Hilfreichster Kommentar

Die Verwendung von Gunicorn mit gevent hat den Fehler nicht behoben.

Alle 82 Kommentare

Der Fehler wird nicht erwartet, aber es gibt nichts aus Ihrem Beispiel, das zeigt, warum er auftritt. Erzählen Sie uns mehr über Ihre Umgebung.

  • Welcher Client wird verwendet, um sich mit Gunicorn zu verbinden?
  • Welcher Reverse-Proxy, falls vorhanden, wird verwendet, um eine Verbindung zu Gunicorn herzustellen?

Erzählen Sie uns mehr über Ihre Umgebung.

  • Welcher Client wird verwendet, um sich mit Gunicorn zu verbinden?
    => Ich sende gerade eine Anfrage von Chromium: http://localhost :5000/
  • Welcher Reverse-Proxy, falls vorhanden, wird verwendet, um eine Verbindung zu Gunicorn herzustellen?
    => Kein Proxy, nur Gunicorn + Flask

Ich habe das Problem gerade in einem völlig neuen Setup reproduziert, hier sind die Schritte:

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

Das hello.py ist genau dieselbe Flask-Anwendung, die ich im ersten Bericht veröffentlicht habe.
Unten ist das komplette Protokoll.

~$ 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 Ich denke, es liegt an der Standardzeitüberschreitung, Ihr Arbeiter war 30 http://docs.gunicorn.org/en/stable/settings.html#timeout

Aus Ihrem Protokoll,

[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)

Ich sehe dasselbe: Worker haben eine Zeitüberschreitung, selbst wenn keine Anfragen bearbeitet werden, mit Sync-Worker.
In diesem Sinne ist das Protokoll der kritischen Ebene ziemlich verwirrend.

Versuchen Sie es mit Gevent Worker.

In diesem Sinne ist das Protokoll der kritischen Ebene ziemlich verwirrend.

Genau, das war meine ursprüngliche Frage: Wenn es ein erwartetes Verhalten ist, warum dann ein kritischer Fehler?
Es wäre auch schön, einige Hintergrundinformationen darüber zu erhalten, warum Worker neu gestartet werden müssen, vielleicht könnte dies dem Design- Dokument hinzugefügt werden.

Ich sehe dies auch (reproduziert durch Verwendung von examples/test.py mit gunicorn test:app -b localhost:9595 --log-level=debug --timeout=5 ) und stimme zu, dass die kritische Ebene etwas verwirrend ist. Ich würde in Ordnung sein, es auf Debug-Ebene zu ändern. @benoitc @tilgovi was denkst du?

Ich denke, der Info-Level könnte ein bisschen besser sein.

Ich hatte das gleiche mit MSYS2 auf Win10, konnte es aber endlich lösen.

in notification() von ...\gunicorn\workers\workertmp.py wird ursprünglich os.fchmod verwendet. Aber es funktioniert nicht in MSYS. Anstelle von os.fchmod habe ich os.utime verwendet. Der Code wird befolgt. Ich denke, es könnte für alle Plattformen funktionieren.

    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 Ich würde nicht erwarten, dass der Worker beendet wird, da keine Anfragen auftreten. Dieser Fehler sollte nur auftreten, wenn der Arbeiter eine Zeit lang > bis zum Timeout beschäftigt war. Der Fehler ist also kritisch. Imo sollten wir die Dokumentation verbessern, um mehr Anwendungsfälle und Antworten auf solche Fehler bereitzustellen.

Wenn der Fehler immer noch auftritt, wenn der Arbeiter nicht beschäftigt ist, passiert etwas anderes und wir haben wahrscheinlich einen Fehler.

[BEARBEITEN]
Gleicher Fehler bei mir.
Mit Django 1.10 / gunicorn 19.6.0 / Python 2.7.15 in python2.7-alpine auf Debian 8.8 und dem Stock-Kernel 3.16 funktionierte alles einwandfrei.
Nach dem Update auf Django 1.11 und gunicorn 19.8.1 schlagen die Worker beim Booten mit [CRITICAL WORKER TIMEOUT] immer wieder fehl.
Ein Downgrade von gunicorn auf 19.6.0 behebt das Problem nicht.
Wir haben den Host-Kernel auf 4.9.0 aktualisiert (es war geplant), und die Arbeiter starteten erfolgreich ohne Fehler.
Aber:

  • wir verwenden 4 Arbeiter
  • nach genau 4 Anrufen an die Django-App wird bei den nächsten Anrufen eine Zeitüberschreitung vorgenommen und [CRITICAL WORKER TIMEOUT] in den Protokollen angezeigt
  • der linux-top-Befehl zeigt 4 gunicorn-Prozesse an, die mit ziemlich hohem CPU-Verbrauch feststecken.

Wir werden gunicorn gevent ausprobieren, um zu sehen, ob wir unsere App wieder online bringen können.

Die Verwendung von Gunicorn mit gevent hat den Fehler nicht behoben.

irgendein Update zu diesem Thema?

Es sieht so aus, als hätte @neocolor einen echten Fehler unter MSYS identifiziert. Es könnte eine separate Ausgabe verdienen.

@bigunyak auf welcher plattform

Für @Tberdy : Was passiert, wenn Sie versuchen, --worker-tmp-dir irgendwo außerhalb des tmpfs-Dateisystems zu setzen? Ich frage mich nur, ob vielleicht Alpine oder Docker oder die Kombination irgendwie stört, wie Arbeiter den Arbiter benachrichtigen.

Siehe auch #1388 für Docker-bezogene tmpfs-Probleme.

Ich habe dieses Problem.

Ich habe dieses Problem auch, Gunicorn Sync hat bis gestern tadellos funktioniert, ut begann mit der Berichterstattung, Arbeiter-Timeout [KRITISCH] mit gevent scheint mein Problem zu lösen, aber ich würde wirklich gerne wissen, warum dies passiert ist .

@timoj58 @cjmash Können Sie weitere Einzelheiten zu dem Problem

@benoitc Ich führe gunicorn aus, um mein Django-Projekt auf Kubernetes zu starten. Meine Gunicorn-Argumente sind --bind=$port --workers=7 --timeout=1200 --log-level=debug --access-logfile - error-logfile - "

die fehler bekomme ich aus den logs

```E [2018-08-09 21:47:56 +0000] [13] [INFO] Booten des Workers mit pid: 13

E [2018-08-09 21:47:56 +0000] [14] [INFO] Booten des Workers mit pid: 14

E [2018-08-09 21:47:56 +0000] [12] [INFO] Booten des Workers mit pid: 12

E [2018-08-09 21:47:56 +0000] [1] [DEBUG] 7 Arbeiter

E [2018-08-09 21:47:56 +0000] [11] [INFO] Booten des Workers mit pid: 11

E [2018-08-09 21:47:55 +0000] [10] [INFO] Booten des Workers mit pid: 10

E [2018-08-09 21:47:55 +0000] [9] [INFO] Booten des Workers mit pid: 9

E [2018-08-09 21:47:55 +0000] [8] [INFO] Booten des Workers mit pid: 8

E [2018-08-09 21:47:55 +0000] [1] [INFO] Arbeiter verwenden: sync

E [2018-08-09 21:47:55 +0000] [1] [INFO] Hören unter: http://0.0.0.0 :4040 (1)

E [2018-08-09 21:47:55 +0000] [1] [DEBUG] Arbiter gebootet

E [2018-08-09 21:47:55 +0000] [1] [INFO] Startschuss für Gunicorn 19.7.1

E raw_paste_global_conf: []

E-Chiffren: TLSv1

E do_handshake_on_connect: Falsch

E suppress_ragged_eofs: True

E ca_certs: Keine

E cert_reqs: 0

E ssl-Version: 2

E-Zertifikatsdatei: Keine

E-Schlüsseldatei: Keine

E proxy_allow_ips: ['127.0.0.1']

E proxy_protokoll: Falsch

E on_exit:

Mitarbeiter_geändert:

E worker_exit:

E child_exit:

E post_request:

E vor_anfrage:

E pre_exec:

E worker_abort:

E worker_int:

E post_worker_init:

E post_fork:

E vor_gabel:

E when_ready:

E on_reload:

E on_starten:

E-Paste: Keine

E-Pythonpfad: Keine

E default_proc_name: art.wsgi

E proc_name: Keine

E statsd_prefix:

E statsd_host: Keine

E enable_stdio_inheritance: Falsch

E syslog_facility: Benutzer

E syslog_prefix: Keine

E syslog: Falsch

E syslog_addr: udp://localhost :514

E logconfig: Keine

E logger_class: gunicorn.glogging.Logger

E capture_output: Falsch

E-Loglevel: debuggen

E Fehlerprotokoll: -

E access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%( wie"

E-Zugangsprotokoll: -

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

E initgroups: Falsch

EU-Maske: 0

E-Gruppe: 0

E-Benutzer: 0

E worker_tmp_dir: Keine

E piddatei: Keine

E raw_env: []

E-Daemon: Falsch

E chdir: /usr/src/app

E sendfile: Keine

E preload_app: Falsch

E check_config: Falsch

E spucken: Falsch

E reload_engine: auto

E nachladen: Falsch

E limit_request_field_size: 8190

E limit_request_fields: 100

E limit_request_line: 4094

E-Keepalive: 2

E Graceful_timeout: 30

E-Timeout: 1200

E max_requests_jitter: 0

E max_requests: 0

E worker_connections: 1000

E-Gewinde: 1

E worker_class: sync

E-Arbeiter: 7

E-Rückstand: 2048

E-Bindung: ['0.0.0.0:4040']

E-Konfiguration: Keine

E [2018-08-09 21:47:55 +0000] [1] [DEBUG] Aktuelle Konfiguration:

I Keine anzuwendenden Migrationen.

I Ausführen von Migrationen:

I Wenden Sie alle Migrationen an: admin, auth, contenttypes, core, Dashboard, jet, oauth2_provider, Sessions

I Durchzuführende Operationen:

E [2018-08-09 21:47:20 +0000] [13] [INFO] Arbeiter verlassen (pid: 13)

E os.path.dirname(os.path.dirname(__file__)), '.env'))

E /usr/src/app/art/wsgi.py:19: UserWarning: /usr/src/app/.env wird nicht gelesen - existiert nicht.

E [2018-08-09 21:47:00 +0000] [21] [INFO] Booten des Workers mit pid: 21

E [2018-08-09 21:47:00 +0000] [1] [INFO] Handhabungssignal: Begriff

E [2018-08-09 21:46:35 +0000] [12] [INFO] Booten des Workers mit pid: 12

E [2018-08-09 21:46:34 +0000] [13] [INFO] Booten des Workers mit pid: 13

E [2018-08-09 21:46:34 +0000] [11] [INFO] Booten des Workers mit pid: 11

E [2018-08-09 21:46:34 +0000] [1] [DEBUG] 7 Arbeiter

E [2018-08-09 21:46:34 +0000] [10] [INFO] Booten des Workers mit pid: 10

E [2018-08-09 21:46:34 +0000] [9] [INFO] Booten des Workers mit pid: 9

E [2018-08-09 21:46:34 +0000] [8] [INFO] Booten des Workers mit pid: 8

E [2018-08-09 21:46:34 +0000] [7] [INFO] Booten des Workers mit pid: 7

E [2018-08-09 21:46:34 +0000] [1] [INFO] Arbeiter verwenden: sync

E [2018-08-09 21:46:34 +0000] [1] [INFO] Hören unter: http://0.0.0.0 :4040 (1)

E [2018-08-09 21:46:34 +0000] [1] [DEBUG] Arbiter gebootet

E [2018-08-09 21:46:34 +0000] [1] [INFO] Startschuss für Gunicorn 19.7.1

E raw_paste_global_conf: []

E-Chiffren: TLSv1

E do_handshake_on_connect: Falsch

E suppress_ragged_eofs: True

E ca_certs: Keine

E cert_reqs: 0

E ssl-Version: 2

E-Zertifikatsdatei: Keine

E-Schlüsseldatei: Keine

E proxy_allow_ips: ['127.0.0.1']

E proxy_protokoll: Falsch

E on_exit:

Mitarbeiter_geändert:

E worker_exit:

E child_exit:

E post_request:

E vor_anfrage:

E pre_exec:

E worker_abort:

E worker_int:

E post_worker_init:

E post_fork:

E vor_gabel:

E when_ready:

E on_reload:

E on_starten:

E-Paste: Keine

E-Pythonpfad: Keine

E default_proc_name: art.wsgi

E proc_name: Keine

E statsd_prefix:

E statsd_host: Keine

E enable_stdio_inheritance: Falsch

E syslog_facility: Benutzer

E syslog_prefix: Keine

E syslog: Falsch

E syslog_addr: udp://localhost :514

E logconfig: Keine

E logger_class: gunicorn.glogging.Logger

E capture_output: Falsch

E-Loglevel: debuggen

E Fehlerprotokoll: -

E access_log_format: %(h)s %(l)s %(u)s %(t)s "%(r)s" %(s)s %(b)s "%(f)s" "%( wie"

E-Zugangsprotokoll: -

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

E initgroups: Falsch

EU-Maske: 0

E-Gruppe: 0

E-Benutzer: 0

E worker_tmp_dir: Keine

E piddatei: Keine

E raw_env: []

E-Daemon: Falsch

E chdir: /usr/src/app

E sendfile: Keine

E preload_app: Falsch

E check_config: Falsch

E spucken: Falsch

E reload_engine: auto

E nachladen: Falsch

E limit_request_field_size: 8190

E limit_request_fields: 100

E limit_request_line: 4094

E-Keepalive: 2

E Graceful_timeout: 30

E-Timeout: 1200

E max_requests_jitter: 0

E max_requests: 0

E worker_connections: 1000

E-Gewinde: 1

E worker_class: sync

E-Arbeiter: 7

E-Rückstand: 2048

E-Bindung: ['0.0.0.0:4040']

E-Konfiguration: Keine

E [2018-08-09 21:46:34 +0000] [1] [DEBUG] Aktuelle Konfiguration:

```

Ich habe mich diesmal etwas Mühe gegeben, das Problem zu reproduzieren, aber es ist immer noch in der neuesten gunicorn-Version 19.9.0 vorhanden.
Die Schritte zum Reproduzieren sind genau die gleichen, die ich in diesem Beitrag beschrieben habe .
Mein System ist Arch Linux x86_64 GNU/Linux (Kernel 4.17.2-1-ARCH), Python 3.6.5
Hier ist ein neuer Log-Trace.

~$ 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

Wie zuvor, um es zu testen, habe ich in Chromium nur http://0.0.0.0 :5000/
Unten ist der Inhalt von Pipfile und Pipfile.lock, damit Sie die genaue Umgebung sehen können.

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

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

[dev-packages]

[requires]
python_version = "3.6"
  • pifile.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": {}
}

Nur zur Info, ich sehe diesen Fehler auch sehr regelmäßig bei:

nohup gunicorn -w 8 --access-logfile=- --bind 127.0.0.1:5000 wsgi &

Ich habe nur eine wsgi.py, die hat

from chart_api import application
if __name__ == "__main__":
    application.run()

Lassen Sie mich wissen, ob ich etwas ausprobieren/experimentieren soll oder ob es Besonderheiten in den Protokollen gibt, die ich überprüfen soll. Ich führe Flask auf einer GCP-VM aus.

Entschuldige die späte Antwort. Ich betreibe es als

gunicorn --log-file=/home/ubuntu/log/gunicorn.log Predictor_ api:app -b localhost:5000 &

Ich habe die Gevent-Einstellung usw. verwendet, aber ich habe mein Design geändert, wofür ich dies benötigt habe, um das Problem zu umgehen, daher die obige Grundeinstellung (die auch fehlgeschlagen ist, aber dies ist ohne Gevent zu erwarten)

Python-Version 3.6
env: aws tensorflow_p36 optimiert (ubuntu)
nginx sitzt vor gunicorn, das eine Flask-App ausführt.

Kolbenversion 1.0.2
nginx-Version 1.10.3
Gunicorn-Version 19.9.0

Ich habe auch die nginx-Timeouts geändert, falls dies die Ursache sein könnte.

Habe das gleiche Problem mit dem Gunicorn-Server

# 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 \

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

Flasche==0,12,1
Gunicorn==19.7.1

Wenn ich den Server mit dem obigen Befehl starte, friert mein System für einige Zeit ein und die Arbeiter-PIDs booten weiter, obwohl ich das Timeout von 120 Sekunden beibehalten habe und der Server keine einzelne Anfrage akzeptiert.

Irgendein Update zu diesem Thema? Ich habe das gleiche Problem

[KRITISCH] ARBEITER-ZEITÜBERSCHREITUNG

Sie fragen sich, ob dies jemand erfolgreich in einem Docker-Image reproduziert hat?

Dies wird auch angezeigt, wenn versucht wird, den ddtrace-run-Worker von datadog in einer vorhandenen Anwendung zu implementieren, die mit gunicorn -k gevent --threads 4 beginnt.

Lustige Spur eines SystemExits habe ich auch noch nie gesehen...
[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

Ich kann dieses Problem lösen, indem ich die Anzahl der Arbeiter und die Anzahl der Threads abgleiche.

Ich hatte workers = (2 * cpu_count) + 1 und keine Threads gesetzt.

Nachdem ich threads = workers geändert hatte, funktionierte alles einwandfrei. Nur für den Fall, falls das jemandem hilft.

So sieht es jetzt aus

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()

Ich bin auf dieses Problem beim Ausführen von Django mit einem einzelnen Docker-Container auf AWS Elastic Beanstalk gestoßen. Ich habe das Problem gelöst, indem ich meine Sicherheitsgruppen repariert habe, um sicherzustellen, dass meine EC2-Instance mit meiner RDS-Instance kommunizieren kann. Mir ist klar, dass dies für 99% der Leute zu diesem Problem möglicherweise nicht die Lösung ist, aber ich hinterlasse diese Notiz, um anderen zu helfen, Stunden zu verschwenden, die in dieses Kaninchenbau fallen.

In meinem Fall wurde das Problem durch Ausführen von systemctl daemon-reload gelöst.
Lange Rede, kurzer Sinn Ich kannte das Standard-Timeout von 30 Sekunden, konnte es jedoch nicht ändern, bis ich dachte, dass ich natürlich den systemd-Daemon neu laden musste, um die Änderungen auf den Dienst anzuwenden.

@bigunyak @benoitc @tilgovi
Nach einer langen Verfolgungsjagd bei Google und einigen Experimenten glaube ich, dass die Hauptursache für dieses Problem der Chrome-"Preconnect/Prediction-Dienst" ist (der standardmäßig sowohl in Chrome als auch in Chromium aktiviert ist).

@jeiting hat einen netten
https://hackernoon.com/chrome-preconnect-breaks-singly-threaded-servers-95944be16400
Einige zusätzliche Lektüre:
https://github.com/corydolphin/flask-cors/issues/147
https://github.com/pallets/flask/issues/2169

TLDR
In einigen Fällen öffnet Chrome/Chromium eine oder mehrere "leere" TCP-Verbindungen (dh es sagt voraus, dass es bald eine andere Ressource abrufen wird). Wenn die "leere" TCP-Verbindung(en) zuerst Ihren Gunicorn-Server trifft, kann jede nachfolgende "echte" Anfrage von Chrome hinter der "leeren" Anfrage stecken bleiben, bis die Worker, die die "leere" Anfrage bearbeiten, das Zeitlimit überschreiten. Dies ist wahrscheinlicher, wenn Sie in gunicorn nur einen einzigen Sync-Worker ausführen. Aber wie meine Experimente gezeigt haben, kann dies sogar passieren, wenn Sie mehrere Sync-Worker ausführen.

Meine Umgebung

  • Mein natives Betriebssystem ist Ubuntu 17
  • Ich habe eine Rest-API, die in einem lokalen Docker-Container ausgeführt wird. Relevante Zeilen aus dem 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
......
  • Ich habe 3 Browser installiert: Firefox 61.0.1, Chromium 67.0.3396.99, Chrome 70.0.3538.102
  • Ich habe eine React-App, die von einem anderen Docker-Container an einem anderen Port bereitgestellt wird
  • Die React-App stellt CORS-AJAX-Anfragen an meine API (es sind CORS-Anfragen, da das Javascript an einem localhost-Port bereitgestellt wird, während es API-Aufrufe an einen anderen localhost-Port sendet).
  • Die Anfrage, die in meinen Experimenten immer "blockiert" wird, ist eine CORS OPTIONS-Anfrage (die vom Browser ausgelöst wird, um um Erlaubnis zu bitten, dann eine POST-Anfrage auszuführen). Es erscheint logisch, dass ein Browser versuchen würde, vorhersagende Verbindungen mit dem OPTIONS-Aufruf herzustellen, da er wahrscheinlich mit einem POST-Aufruf nachfolgen wird.

Versuch 1
Gunicorn-Konfiguration: 1 Sync-Worker (Standard 30s Timeout)

Firefox: Bei fast jedem Laden der Reaktionsseite wird die CORS OPTIONS-Anfrage für 5 Sekunden blockiert und ist dann erfolgreich.
Chromium: Bei JEDEM Seitenladevorgang wird die CORS OPTIONS-Anfrage für 1,5 Minuten blockiert!!!! und dann gelingt.
Chromium (Vorhersagedienst deaktiviert): Alles wird gut geladen
Chrome: Alles wird gut geladen

Experiment 2
Gunicorn-Konfiguration: 4 Sync-Worker (Standard 30s Timeout)

Firefox: Alles lädt gut
Chromium: Bei jedem dritten Seitenladevorgang wird die CORS OPTIONS-Anfrage 30 Sekunden lang blockiert und ist dann erfolgreich.
Chromium (Vorhersagedienst deaktiviert): Alles wird gut geladen
Chrome: Alles wird gut geladen

Experiment 3
Gunicorn-Konfiguration: 8 Sync-Worker (Standard 30s Timeout)

Firefox: Alles lädt gut
Chrom: Alles lädt gut
Chrome: Alles wird gut geladen

Experiment 4
Führen Sie den Flask-Entwicklungsserver mit threaded=True

Firefox: Alles lädt gut
Chrom: Alles lädt gut
Chrome: Alles wird gut geladen

Zusammenfassung des Experiments

  • Firefox scheint auch einen Vorhersagedienst zu haben, aber er scheint anmutiger zu sein. (Versuch 1)
  • Chrom scheint beim Erstellen von "Vorhersage" -Verbindungen am aggressivsten zu sein. Es scheint bis zu 3-4 "Vorhersage" -Verbindungen während einer OPTIONS-Anfrage zu starten (Experiment 1 und 2)
  • Obwohl Chrome auch den Vorhersagedienst aktiviert hat, hat er überraschenderweise in keinem der Experimente Probleme verursacht (vielleicht unterscheidet sich die Reihenfolge oder die Anzahl der "Vorhersage" -Verbindungen von Chromium).

Lösung
In Produktion: Die einfachste Lösung besteht darin, nginx vor Gunicorn zu platzieren. Wenn Sie verstehen möchten, warum nginx dieses Problem löst, finden Sie hier einen schönen Artikel, der es erklärt: https://www.brianstorti.com/the-role-of-a-reverse-proxy-to-protect-your-application-against -langsame-Clients/

In dev: Die einfachste Lösung besteht darin, den Flask Dev-Server mit threaded=True auszuführen. Oder Sie können den Vorhersagedienst in Chrome/Chromium deaktivieren.

Gunicorn Debug-Verbesserungen
Um ein solches Problem in Zukunft zu beheben, ist es meiner Meinung nach eine gute Idee, Debugprotokollanweisungen neben den select() und accept() Aufrufen im Sync-Worker hinzuzufügen.
https://github.com/benoitc/gunicorn/blob/e974f30517261b2bc95cfb2017a8688f367c8bf3/gunicorn/workers/sync.py#L26
https://github.com/benoitc/gunicorn/blob/e974f30517261b2bc95cfb2017a8688f367c8bf3/gunicorn/workers/sync.py#L34
Dies würde anzeigen, dass ein Worker eine neue TCP-Verbindung akzeptiert hat, aber keine Daten empfängt.

@asnisarenko super

Es kann das Gunicorn sein, denn Single-Threaded-Sync-Worker benötigen einige neue einstellbare, aggressive Client-Drop für Clients, die nicht innerhalb einer angemessenen Zeit mindestens eine erste Anforderungs-Header-Zeile, wenn nicht alle Header, senden.

Wenn dies in Ihrer App passiert, können Sie einen temporären Diagnosecode hinzufügen:

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)

Hoffentlich sollte dies zeigen, wo Ihre App hängt.

Zum Beispiel habe ich es irgendwie geschafft, import flask vor gevent.monkey.patch_all() und so wurde das app._before_request_lock meiner Flasche zu einem Nicht-Gevent-Lock (dh einfach ungepatcht threading.Lock ). In einem solchen Fall würden zwei Anfragen kurz hintereinander beim Start der App dazu führen, dass sie aufhängt (2. Anfrage würde den gesamten Thread sperren). Aber das war mein Fehler, und Ihr Fehler kann sich unterscheiden.

@asnisarenko Ich bin mir nicht sicher, warum Sie einen Hang haben. Sie brauchen _keinen_ Worker pro Verbindung, da jeder Worker Tausende von Verbindungen kooperativ handhaben kann (solange der Handhabungscode nicht die CPU monopolisiert / den gesamten Thread sperrt). Insbesondere wenn der Browser die Anfrage anhält, bedeutet dies einfach, dass, wenn gunicorn read() aus dem Socket kommt, ein Greenlet blockiert wird, aber da read mit Affen gepatcht werden sollte, ergibt sich die anderen Grünlinge.

@ikonst
In diesem Problem geht es darum, gunicorn mit der Standardkonfiguration auszuführen. Die Standardworkerklasse ist sync http://docs.gunicorn.org/en/stable/settings.html#worker -class

sync Worker verwenden ein Pre-Fork-Modell und jeder Worker verarbeitet jeweils eine TCP-Verbindung/-Anfrage.

Ich weiß nicht, was dies bei mir verursacht hat, aber der Wechsel vom Standard-Arbeitstyp sync zu eventlet das Problem behoben:

CMD pipenv run gunicorn webapp -b 0.0.0.0:8080 -k eventlet

Viel Glück.

Vielleicht hilft das nur mir, aber da ich 7 Stunden gebraucht habe, um dieses Problem auf meiner Seite zu debuggen (eine Flask/Gunicorn-App, die in Docker auf EC2 läuft), ist es ein kleiner Sieg, wenn ich diese Kopfschmerzen einigen Leuten ersparen kann.

Das Containerspeicherlimit war zu niedrig.

Wenn ich in Zukunft Speicherlecks habe, werde ich versuchen, ein höheres Speicherlimit festzulegen, aber im Moment reicht kein Limit.

Danke

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)

Du hilfst mir sehr. EHU )))

Wohin geht diese trace_on_abort() Methode? In der App-Codedatei? Braucht es eine Anmerkung?

@mattg-vbt füge dies am Anfang deiner App hinzu, wenn du debuggen musst, und entferne es, wenn du mit dem Debuggen fertig bist

@ikonst Ich habe dies zu meiner App hinzugefügt, aber ich sehe nicht, dass es getroffen wird. Ich erhalte das Worker-Timeout, aber diese Methode wird nicht getroffen.

@mattg-vbt können Sie versuchen, kill -ABRT $pid auszuführen, um zu sehen, wie die Funktion print_trace aufgerufen wird? (Die Idee ist, dass Sie SIGABRT von werkzeug erhalten, wenn Ihr Worker eine Zeitüberschreitung hat, aber zuerst überprüfen wir, ob es überhaupt aufgerufen wird)

@asnisarenko für die weniger versierten unter uns, wie würde ich dann das Profil aktualisieren?

web gunicorn app:app -k gevent --worker-connections 1000 ?

@SumNeuron
Wenn Sie Gevent-Worker verwenden (anstelle von Sync-Workern), sollten Sie dieses Problem nicht haben. Der von Ihnen gepostete Befehl scheint also in Ordnung zu sein.

Ich bekomme dieses Problem mit gevent-Workern nur bei der Initialisierung, was etwas nervig ist, da ich einige Aufgaben verarbeite, bevor ich meine App starte. Aber ich setze vorerst ein hohes Timeout.
Ich habe hier ein reproduzierbares Testrepo gepostet: https://github.com/zamponotiropita/test-gunicorn-worker-timeout -> test_0 schlägt fehl, test_1 und test_2 bestehen

@zamponotiropita Versuchen Sie, dies pro Worker oder pro App vor dem Forking zu tun?

@ikonst bitte überprüfen Sie die Ausführungsdatei run.sh , sie ist pro Arbeiter. Das Problem trat nicht beim Vorladen auf, aber ich hatte Probleme beim Verbinden mit der Datenbank beim Vorladen, da das App-Objekt (und damit zusammen die Datenbankverbindung) kopiert und die Prozesse beim Forken übergeben wird -> meine Datenbank konnte nicht umgehen identische Verbindungen von Master und Arbeitern, und ich konnte keinen Workaround finden

Ich habe ein ähnliches Problem. Ich versuche, mit Flask viele Daten on-the-fly zu generieren, indem ich
diese Methode, und sie schlägt fehl, weil der Worker das Zeitlimit überschreitet, nachdem das, was in --timeout abgelaufen ist. Ein minimales Beispiel zum Reproduzieren:

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')

Führen Sie dann gunicorn --timeout 10 test_gunicorn_timeout:app und wenn Sie nach 10 Sekunden localhost:8000 anfordern, erhalten Sie ein
[CRITICAL] WORKER TIMEOUT .

Ich habe auch versucht, mit -k gevent und -k eventlet laufen und es hat sich nichts geändert.

Ich verwende Windows 10 Pro. Mit Docker Compose
gunicorn app -b 0.0.0.0:8000 -k gevent
Hat für mich funktioniert, indem ich gevent in meinem Python-Container installiert habe
So installieren Sie gevent

Führen Sie dann gunicorn --timeout 10 test_gunicorn_timeout:app und wenn Sie nach 10 Sekunden localhost:8000 anfordern, erhalten Sie ein
[CRITICAL] WORKER TIMEOUT .

Ich habe auch versucht, mit -k gevent und -k eventlet laufen und es hat sich nichts geändert.

@ltskv

Haben Sie eine Lösung für das Problem [CRITICAL] WORKER TIMEOUT gefunden?

Ich habe ein ähnliches Problem mit einem Kolben-Streaming-Endpunkt, den ich auf Heroku bereitstellen möchte (der Gunicorn verwendet). Dort soll das Proxy-Frontend die Verbindung aufrechterhalten, solange innerhalb von 30 Sekunden einige Daten gesendet werden, aber es scheint, dass gunicorn den Prozess einfach beendet, wenn er nicht innerhalb von 30 Sekunden abgeschlossen ist, obwohl er noch läuft und Daten produziert.

Die Gunicorn-Dokumentation ist mir in diesem Punkt nicht ganz klar. Für --timeout steht, dass Workers silent for more than this many seconds are killed and restarted. Aber es scheint, dass Arbeiter nach 30 Sekunden getötet werden, obwohl sie immer noch Daten produzieren?

Die Gunicorn-Dokumentation ist mir in diesem Punkt nicht ganz klar. Für --timeout heißt es, dass Arbeiter, die länger als so viele Sekunden schweigen, getötet und neu gestartet werden. Aber es scheint, dass Arbeiter nach 30 Sekunden getötet werden, obwohl sie immer noch Daten produzieren?

@kurt-hectic, dass die Dokumentation verbessert werden sollte. Mit stumm meinen wir stumm aus der Perspektive des Schlichterprozesses, der mit den Arbeitern über eine temporäre Datei kommuniziert. Wenn der Worker damit beschäftigt ist, Daten zu senden, aktualisiert er diese Datei nicht. Aus Sicht des Schiedsrichters fehlen dem Arbeiter Herzschläge.

Siehe auch #1974.

Wenn Sie einen anderen als den Standard-Worker verwenden, sollte der synchrone Worker das Problem mit dem Streamen großer Körper abschwächen, da die anderen Worker die temporäre Datei selbst bei der Verarbeitung von Anforderungen als Heartbeat verwenden.

@kurt-hectic Ich habe die Option -k gevent noch einmal überprüft und sleep(0) zwischen den Generatoriterationen eingefügt und es hat tatsächlich für mich funktioniert (ich bin mir nicht sicher, warum es damals nicht funktionierte) Ich habe die Frage aber gepostet).

--timeout=5

Dies ist die häufigste Ursache für dieses Problem.

Ich hoffe, meine Lösung konnte dir helfen. Ich bin vor einigen Tagen auf dieses kritische Worker-Timeout-Problem gestoßen und habe einige Lösungen ausprobiert. Es funktioniert jetzt gut.

Hier mein Verständnis und Lösungsansätze:

  1. Versuchen Sie, in gunicorn vorzuladen

Es schlägt fehl, die Worker zu booten, weil es mehr Zeit braucht, um das Paket zu laden, z. B. das Tensorflow-Backend, um den Dienst zu starten. Wenn Sie also eine langsame App-Startzeit feststellen, versuchen Sie, die Vorladeoption in gunicorn zu aktivieren (siehe https://devcenter.heroku.com/articles/python-gunicorn#advanced-configuration).

gunicorn hallo:app --preload

  1. Versuchen Sie, die Auszeit für Gunicorn zu erhöhen

Das Standard-Timeout beträgt 30 Sekunden. Wenn Ihre Anwendung wirklich viel Zeit benötigt, um eine API fertigzustellen, erhöhen Sie das Timeout.

gunicorn hallo:app --timeout 10

Aus meiner Sicht macht es jedoch keinen Sinn, wenn eine API mehr als 1 Minute braucht, um fertig zu werden. Wenn dies der Fall ist, versuchen Sie, in Ihrem Code Fortschritte zu erzielen.

  1. Wenn Sie k8s verwenden, können Sie auch eine timeoutSeconds für Ihren Container/Ihr Image in yaml festlegen.

Ich stand heute vor dem gleichen Problem. In meinem Fall brauchte die API etwa eine Minute, um die Daten zu berechnen und an den Client zurückzugeben, was zu CRITICAL WORKER TIMEOUT-Fehlern führte. Ich habe es gelöst, indem ich das Timeout-Flag für Gunicorn auf mehr als eine Minute erhöht habe - es hat funktioniert, das Problem kam nicht wieder. Hoffe das hilft. Ich verwende uvicorn.workers.UvicornWorker.

Ich habe dies behoben, indem ich gnuicorn zusätzliche Arbeiter hinzugefügt habe:

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

Keine Ahnung warum.

Vielleicht hatten Sie einen Deadlock? Stellt Ihre App Anfragen an sich selbst?

Am So, 5. Januar 2020, 10:52 alpinechicken, schrieb [email protected] :

Ich habe dies behoben, indem ich gnuicorn zusätzliche Arbeiter hinzugefügt habe:

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

Keine Ahnung warum.


Sie erhalten dies, weil Sie einen Kommentar abgegeben haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/benoitc/gunicorn/issues/1801?email_source=notifications&email_token=AAAEQJVQRCW3C63EZJWIN5DQ4G3WTA5CNFSM4FDLD5PKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63VQRCW3C63EZJWIN5DQ4G3WTA5CNFSM4FDLD5PKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63VQRCW2HIDZLOKTDN5WWXE96
oder abmelden
https://github.com/notifications/unsubscribe-auth/AAAEQJXZM4NLK56DZMFSZALQ4G3WTANCNFSM4FDLD5PA
.

Ja, eine Route ruft eine andere an - ist das schlimm?

Das bedeutet, dass Sie mindestens zwei Arbeiter benötigen, sonst wird Ihr Server dies tun
Sackgasse. Die Anfrage wird warten, bis der Server auf die zweite antwortet
Anfrage (die in die Warteschlange gestellt werden würde).

Sie erhalten eine gleichzeitige Anfrage pro Mitarbeiter.

Am Mo, 6. Jan 2020, 02:45 alpinechicken, [email protected] schrieb:

Ja, eine Route ruft eine andere an - ist das schlimm?


Sie erhalten dies, weil Sie einen Kommentar abgegeben haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/benoitc/gunicorn/issues/1801?email_source=notifications&email_token=AAAEQJSFEFBBI6AMZJCM4C3Q4KLOJA5CNFSM4FDLD5PKYY3PNVWWK5
oder abmelden
https://github.com/notifications/unsubscribe-auth/AAAEQJXTCPOFIZJU5PUPOODQ4KLOJANCNFSM4FDLD5PA
.

Ach das macht Sinn. Danke!

Am Di, 7. Januar 2020 um 6:23 Uhr schrieb bobf [email protected] :

Das bedeutet, dass Sie mindestens zwei Arbeiter benötigen, sonst wird Ihr Server dies tun
Sackgasse. Die Anfrage wird warten, bis der Server auf die zweite antwortet
Anfrage (die in die Warteschlange gestellt werden würde).

Sie erhalten eine gleichzeitige Anfrage pro Mitarbeiter.

Am Mo, 6. Jan 2020, 02:45 alpinechicken, [email protected] schrieb:

Ja, eine Route ruft eine andere an - ist das schlimm?


Sie erhalten dies, weil Sie einen Kommentar abgegeben haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
<
https://github.com/benoitc/gunicorn/issues/1801?email_source=notifications&email_token=AAAEQJSFEFBBI6AMZJCM4C3Q4KLOJA5CNFSM4FDLD5PKYY3PNVWWK5TUL52HS4DFVREXG43VMVBWIEKTPXI#
,
oder abmelden
<
https://github.com/notifications/unsubscribe-auth/AAAEQJXTCPOFIZJU5PUPOODQ4KLOJANCNFSM4FDLD5PA

.


Sie erhalten dies, weil Sie einen Kommentar abgegeben haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/benoitc/gunicorn/issues/1801?email_source=notifications&email_token=AAH2WRPVPVO2EJ53BKQW5B3Q4OHLRA5CNFSM4FDLD5PKYY3PNVWWK3TUL52HS4DFVREXG43VMVBJKDN90NWWQG
oder abmelden
https://github.com/notifications/unsubscribe-auth/AAH2WRM2LLIB4O6OHCU5UG3Q4OHLRANCNFSM4FDLD5PA
.

worker_class', 'sync')

Ich kann dieses Problem lösen, indem ich die Anzahl der Arbeiter und die Anzahl der Threads abgleiche.

Ich hatte workers = (2 * cpu_count) + 1 und keine Threads gesetzt.

Nachdem ich threads = workers geändert hatte, funktionierte alles einwandfrei. Nur für den Fall, falls das jemandem hilft.

So sieht es jetzt aus

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()

Laut gunicorn doc ändert es die Worker-Klasse von sync in gthread, wenn mehr als ein Thread erwähnt wird.
PS:-
Wenn Sie versuchen, den Sync-Worker-Typ zu verwenden und die Thread-Einstellung auf mehr als 1 setzen, wird stattdessen der gthread-Worker-Typ verwendet.

Mein Fall:

Umgebung: Ubuntu18.04+ gunicorn+ nginx +fläschchen

pip installiere gunicorn[gevent] in meiner virtuellen Umgebung

Ändere gunicorn -b localhost:8000 -w 4 web:app in gunicorn -b localhost:8000 -k gevent web:app

Es klappt.

Vielen Dank an alle hier, die so viel getan haben, um sich gegenseitig bei der Lösung ihrer Probleme zu helfen. Bitte posten Sie weiter zu diesem Thema, wenn es Ihnen angemessen erscheint.

Ich schließe dieses Problem jedoch, weil ich glaube, dass hier kein Fehler in Gunicorn vorliegt und ich denke, dass keine Maßnahmen ergriffen werden müssen, obwohl ich gerne dabei helfen werde, PRs zu überprüfen, die versuchen, Dokumentation dafür irgendwie hinzuzufügen oder zu verbessern Meldungen protokollieren.

Bitte verstehen Sie meine Absicht nicht falsch. Wenn Sie einen Fehler in Gunicorn vermuten und weiter diskutieren möchten, tun Sie dies bitte. Öffnen Sie vorzugsweise ein neues Ticket mit einer Beispielanwendung, die Ihr Problem reproduziert. An dieser Stelle gibt es jedoch zu viele verschiedene Probleme, Lösungen und Gespräche in dieser Ausgabe, als dass sie sehr gut lesbar wäre.

Wenn Sie Gunicorn ohne einen puffernden Reverse-Proxy davor ausführen, _werden_ Sie aus verschiedenen Gründen Zeitüberschreitungen mit dem Standard-Sync-Worker. Gängige sind:

  • Langsame Kunden
  • Preconnect/Prefetch-Verbindungen, die von Browsern und Proxys offen gelassen werden
  • Lange Antworten durch Aufrufen externer APIs oder viel CPU-gebundene Arbeit

Sie können zu asynchronen oder Threaded-Worker-Typen wechseln oder Gunicorn hinter einen puffernden Reverse-Proxy stellen. Wenn Sie wissen, dass Ihre Zeitüberschreitungen darauf zurückzuführen sind, dass Ihr eigener Code langsame Aufrufe externer APIs durchführt oder erhebliche Arbeit leistet, die Sie erwarten, können Sie die Option --timeout erhöhen.

Das bedeutet, dass Sie mindestens zwei Arbeiter benötigen, sonst wird Ihr Server blockiert. Die Anfrage wartet, bis der Server auf die zweite Anfrage antwortet (die in die Warteschlange gestellt würde). Sie erhalten eine gleichzeitige Anfrage pro Mitarbeiter.

Am Mo, 06.01.2020, 02:45 Uhr alpinechicken, @ . * > wrote: Yep eine Route ruft eine andere an - ist das schlimm?

Ist dies der Fall, wenn die Funktion 'redirect' als Rückgabewert für eine Route aufgerufen wird?

Ist dies der Fall, wenn die Funktion 'redirect' als Rückgabewert für eine Route aufgerufen wird?

Nein. Eine Flask-Weiterleitung antwortet mit einer HTTP-Weiterleitung und der Worker kann dann eine neue Anfrage annehmen. Der Client stellt eine weitere Anforderung, wenn er diese Antwort sieht, und erhält diese Anforderung immer dann, wenn ein Worker bereit ist.

Ich habe dies behoben, indem ich gnuicorn zusätzliche Arbeiter hinzugefügt habe:

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

Keine Ahnung warum.

Steht das im Zusammenhang mit dem @anilpai- Kommentar workers=1 + (multiprocessing.cpu_count() * 2) .. gesetzt hat?

Ich hatte ein ähnliches Problem. Es stellte sich heraus, dass ich einen Fehler in meinem Einstiegspunkt zur Anwendung hatte. Beim Debuggen schien es, als würde ich im Wesentlichen eine Flaschen-App von gunicorn starten, deren Mitarbeiter anschließend in eine unendliche Verbindungsschleife eintreten, die alle 30 Sekunden abläuft.

Ich bin sicher, dass dies nicht alle oben genannten Benutzer betrifft, aber möglicherweise einige davon.

In meiner module/wsgi.py Datei, die ich mit gunicorn module.wsgi betreibe, hatte ich -

application = my_create_app_function()
application.run(host="0.0.0.0")

Wobei ich hätte -

application = my_create_app_function()
if __name__ == "__main__":
     application.run(host="0.0.0.0")

Im Wesentlichen möchten Sie nicht application.run() anrufen, wenn Sie Gunicorn verwenden. Das __name__ unter gunicorn wird nicht "__main__" , aber es wird in Flask sein, sodass Sie weiterhin lokal debuggen können.

Ich konnte in den Gunicorn-Dokumenten keinen Hinweis darauf finden, könnte mir aber vorstellen, dass es sich um einen häufigen Fehlerfall handelt, daher ist möglicherweise eine Warnung erforderlich.

Dies geschieht immer noch. Das Hinzufügen von --preload zum Gunicorn-Anruf hat das Problem für mich behoben.

Ist dieser Fehler immer noch nicht behoben? Ich beobachte genau dieses Verhalten.

Gunicorn beginnt in systemd so:

[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

Worker-Prozess läuft ständig ab und startet neu:

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 ist eine trivale Flask-App.

Ist dieses Problem als Don't Fix geschlossen?

Das gleiche Problem hatte ich auch

Aber nach dem Debuggen kann ich feststellen, dass, während gunicorn die Django-App startet, eine der Abhängigkeiten länger als die erwartete Zeit dauerte (in meinem Fall eine externe DB-Verbindung), wodurch der gunicron Worker zum Timeout führte

Als ich das Verbindungsproblem behoben habe, wurde auch das Zeitüberschreitungsproblem behoben ...

Dies wäre nicht mein Fall. Ich habe mit dem App-Typ "Hello, World" ohne Abhängigkeiten getestet. Ich bin immer noch verwirrt darüber, aber es scheint nicht möglich zu sein, Gunicorn mit langem Faden zu haben. Worker-Prozess wird neu gestartet und beendet daher den lang laufenden Thread.

@leonbrag
Dies ist wahrscheinlich KEIN Gunicorn-Bug. Siehe meine Empfehlung oben im Thread. Es ist ein Nebeneffekt, wenn Browser leere "vorhergesagte" TCP-Verbindungen senden und gunicorn mit nur wenigen Sync-Workern ohne Schutz vor leeren TCP-Verbindungen ausführen.

Gibt es eine Referenzarchitektur / ein Referenzdesign, das eine ordnungsgemäße Einrichtung der Gunicorn-Flaschen-App mit einem langen (permanenten) Worker-Thread zeigt?

Wenn dies kein Fehler ist, scheint es ein Artefakt oder eine Einschränkung der Gunicorn-Architektur / des Designs zu sein.

Warum sollte der Sync-Worker nicht ewig laufen und Client-Verbindungen akzeptieren. Ein solcher Worker würde den Socket nach Bedarf schließen, jedoch ohne Beenden weiterlaufen (und daher den Worker-Thread weiterlaufen lassen).

@leonbrag
Sie sollten genauer angeben, welches Problem Sie lösen möchten.

Das in diesem Thread besprochene Problem tritt in der Entwicklungsumgebung auf und die einfachste Lösung besteht darin, entweder mehr Sync-Worker hinzuzufügen oder Threaded-Worker zu verwenden.

Wenn Sie dieses Problem im Produktions-Setup vermeiden möchten, können Sie gevent-Worker verwenden oder eine Nginx vor Gunicorn stellen.
Einige PaaS legen bereits eine nginx vor Ihren Docker-Container, sodass Sie sich keine Sorgen machen müssen. Auch hier hängt die Lösung vom Kontext und den Details ab.

Dies ist eine gute Lektüre.
https://www.brianstorti.com/the-role-of-a-reverse-proxy-to-protect-your-application-against-slow-clients/

Sie können die Designseite aus der Dokumentation überprüfen. Asynchrone Arbeiter sind eins
Möglichkeit, lange Aufgaben auszuführen.

Am Sa, 8. August 2020 um 18:00 Uhr schrieb leonbrag [email protected] :

Gibt es eine Referenzarchitektur/ein Design, das einen richtigen Weg zur Einrichtung zeigt?
Gunicorn-Flaschen-App mit langem (permanentem) Worker-Thread ?

Wenn dies kein Fehler ist, scheint es ein Artefakt oder eine Einschränkung der
Gunicorn Architektur/Design.

Warum sollte der Sync-Worker nicht ewig laufen und Client-Verbindungen akzeptieren. Eine solche
Der Arbeiter würde den Socket nach Bedarf schließen, aber weiterlaufen, ohne ihn zu beenden
(und daher wird der Worker-Thread weiter ausgeführt).


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/benoitc/gunicorn/issues/1801#issuecomment-670944797 ,
oder abmelden
https://github.com/notifications/unsubscribe-auth/AAADRIWRQGIP3R5PMVJ5ENTR7VZA3ANCNFSM4FDLD5PA
.

>

Von meinem Handy gesendet

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

Ich habe mein Problem behoben, indem ich --timeout . erhöht habe

Siehe auch #1388 für Docker-bezogene tmpfs-Probleme.

Oh, vielen Dank Randall, ich habe vergessen, --worker-tmp-dir /dev/shm zu gunicorn-Argumenten hinzuzufügen, als ich gunicorn in Docker ausgeführt habe.

Übrigens, reichen 64 MB für den Gunicorn-Cache?

gunicorn app:app --timeout 1000
Oder
gunicorn app:app --preload

Hat für mich funktioniert... Ich bevorzuge eine Auszeit.

Seltsam, ich habe --worker-tmp-dir /dev/shm hinzugefügt,

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

Um sicherzustellen, dass /dev/shm Ramfs ist, habe ich es verglichen:

image

Die Parameter sind als nächstes:

    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: Ich verwende PyPy

@attajutt timeout ist nett, aber Sie riskieren, dass der Gunicorn-Master-Prozess erst nach 1000 Sekunden einen Aufhänger in Ihrem Worker-Prozess erkennt und Sie viele Anfragen verpassen. Es wird auch schwer zu erkennen sein, wenn nur einer von mehreren Arbeitern auflegt. Ich würde zumindest keine 1000 machen.

@ivictbor danke für lmk. 1000 dient als Referenz. Trotzdem habe ich die App ins Rollen gebracht, sobald sie geladen ist. Sie läuft einwandfrei.

Ich habe dieses Fehlerproblem auch und nach mehreren Malen habe ich festgestellt, dass das Problem wahrscheinlich verursacht wird:

  1. Nginx-Konfiguration
  2. Gunicorn/Uwsgi

Wenn Sie Ihre App in einer Cloud wie GAE bereitstellen, werden keine Hinweisfehler angezeigt.
Sie können versuchen, den Fehler mit dieser Falllösung aufzudecken :

Wenn 502 angehoben, fehlerhaftes Gateway;
wird wohl 2 möglichkeiten haben:

  1. Gunicorn läuft nicht
  2. Gunicorn hat eine Auszeit

komplette Lösung hier erklärt: https://www.datadoghq.com/blog/nginx-502-bad-gateway-errors-gunicorn/

Ich hoffe, das kann jemand beheben, der einen Fehler in [CRITICAL] WORKER TIMEOUT erhalten hat

Hinzufügen einer weiteren Möglichkeit für diejenigen, die diesen Thread finden ...

Dies kann auch durch von Docker auferlegte Ressourcenbeschränkungen verursacht werden, die für Ihre Webanwendung zu niedrig sind. Ich hatte zum Beispiel die folgenden Einschränkungen:

services:
  web_app:
    image: blah-blah
    deploy:
      resources:
        limits:
          cpus: "0.25"
          memory: 128M

und diese waren offensichtlich zu niedrig für gunicorn so dass ich ständig den Fehler [CRITICAL] WORKER TIMEOUT , bis ich die Einschränkungen entfernte.

Für Gunicorn sind diese Ressourcen völlig in Ordnung. Aber du musst es wirklich
Flugzeug für die Anzahl der Arbeiter und die Ressourcen, die für Ihre
Anwendung. 128M und 0,25cpu scheinen für eine Webanwendung wirklich niedrig zu sein
geschrieben in Python.... im Allgemeinen benötigen Sie mindestens 1 Kern /vcpu und
512 MB RAM als absolutes Minimum.

Am Fr 26 Mär 2021 um 02:14, Colton Hicks @ . * > schrieb:

Hinzufügen einer weiteren Möglichkeit für diejenigen, die diesen Thread finden ...

Dies kann auch durch von Docker auferlegte Ressourcenbeschränkungen verursacht werden, die
sind für Ihre Webanwendung zu niedrig. Ich hatte zum Beispiel folgendes
Einschränkungen:

Dienstleistungen:
Web-App:
Bild: bla-bla
einsetzen:
Ressourcen:
Grenzen:
CPU: "0,25"
Speicher: 128M

und diese waren offensichtlich zu niedrig für Gunicorn, also bekam ich ständig die [CRITICAL]
WORKER TIMEOUT-Fehler, bis ich die Einschränkungen entfernt habe.


Sie erhalten dies, weil Sie erwähnt wurden.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/benoitc/gunicorn/issues/1801#issuecomment-807855647 ,
oder abmelden
https://github.com/notifications/unsubscribe-auth/AAADRITPZB7BMA6QW7LFNVLTFPNV3ANCNFSM4FDLD5PA
.

>

Von meinem Handy gesendet

--timeout=1000 hat bei mir funktioniert. Das Problem war ein GCP-Computer mit niedriger CPU-Ressource. Es hat auf meinem lokalen Computer mit dem Standard-Timeout funktioniert.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen