<p>gunicorn KRITISCHE ARBEITER-AUSZEIT</p>

Erstellt am 21. Jan. 2017  ·  18Kommentare  ·  Quelle: benoitc/gunicorn

Ich betreibe ein Gunicorn mit den folgenden Einstellungen:
gunicorn --worker-class gevent --timeout 30 --graceful-timeout 20 --max-requests-jitter 2000 --max-requests 1500 -w 50 --log-level DEBUG --capture-output --bind 0.0.0.0:5000 run:app und ich sehe bei allen außer 3 Arbeitern das [CRITICAL] WORKER TIMEOUT . Nach einer gewissen Zeit kann Gunicorn keine Arbeiter mehr spawnen oder ist zumindest sehr langsam darin, sie zu spawnen. Dadurch wird der Server nicht erreichbar und jede Anfrage unerreichbar.

Ich habe die Anzahl der Arbeiter auf 3 reduziert und jedem Arbeiter 2 Threads gegeben und jetzt sehe ich dieses Problem nicht mehr.

Ich kann keinen Stacktrace aus den Timeouts abrufen, aber das scheint nach einer bestimmten Anzahl von Workern nicht mehr möglich zu sein?

( unconfirmed - Bugs -

Hilfreichster Kommentar

Falls dieses Problem weiterhin besteht, überprüfen Sie bitte die Ressourcenverfügbarkeit für die Anwendung, erhöhen Sie zusätzlich das Timeout und ändern Sie den Worker-Klassentyp

Ich hatte dieses Problem, als ich versuche, meine Anwendung mit Docker Swarm bereitzustellen, und habe festgestellt, dass ich die Ressource für die Anwendung zu niedrig begrenzt habe. Die Erhöhung der Ressource löst das Problem für mich

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

Ich denke, das ist kein Fehler, sondern nur die Art und Weise, wie wir unsere Apps konfigurieren

Alle 18 Kommentare

ein Worker-Timeout bedeutet, dass er den Arbiter nicht rechtzeitig benachrichtigt hat, dass er am Leben ist. Haben Sie während einer Anfrage eine Aufgabe ausgeführt, die länger als das Timeout dauern könnte?

@jseaidou Stoß.

Sorry für die späte Antwort @benoitc. Das Problem, das ich sehe, sind die nicht aktiven Threads, die dies tun. Meine aktiven Threads haben keine Zeitüberschreitung, meine inaktiven Threads geben unter geringerer Last mehr kritische Zeitüberschreitungsfehler als nur eine ordnungsgemäße Zeitüberschreitung. Ich habe von Gevent zu Tornado gewechselt und das scheint das Hang-Problem behoben zu haben, aber ich sehe immer noch 3 Arbeiter, die alle 30 Sekunden das kritische Timeout geben. Wenn es sich um ein normales Timeout handelt, sollte es kein kritischer Fehler sein.

ich stehe vor genau dem gleichen Problem.
Gunicorn 19.7.1
gevent 1.2.1
Python 3.5.3
Läuft in Docker, Image basiert auf offiziellem " python:3.5 "

@jseaidou es ist ein normales Timeout in dem Sinne, dass der Schiedsrichter darauf reagiert. Es ist kritisch, weil es normalerweise nicht passieren sollte.

Höchstwahrscheinlich führt einer Ihrer Mitarbeiter eine Blockierungsoperation durch, die den Gunicorn-Mitarbeiter daran hindert, den Schiedsrichter zu benachrichtigen. Wenn Sie eine lange Operation haben, stellen Sie sicher, dass Sie den geven-Scheduler von Zeit zu Zeit durch Schlafen oder ähnliches auslösen. oder alles, was auch den Tornado-Scheduler zurückruft.

Wie kann ich das Problem reproduzieren?

@saabeilin gleich ^^

Ich sehe das Gleiche: Die Zeitüberschreitung der Mitarbeiter, auch wenn keine Anfragen bearbeitet werden. Ich habe lediglich meinen Container auf AWS ECS gestartet.

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

Bei lokaler Ausführung tritt dies nicht auf. :-/

Sieht so aus, als hätte der Wechsel zu gevent Mitarbeitern das Problem für mich gelöst. ¯\_(ツ)_/¯

Duplikat von #1194, denke ich.

Ich habe dies in letzter Zeit wiederholt gesehen, und für mich scheint es damit verbunden zu sein, den Laptop in den Ruhezustand zu versetzen. Wenn ich den Deckel öffne, werden eine Reihe dieser Nachrichten angezeigt. Ich bin mir nicht sicher, ob das hilft, aber ich dachte, ich erwähne es mal...

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

Zeitüberschreitung 30 Sekunden
GET-Anfrage

ubuntu 16.04
Kolben 0.12.2
Python 3.6.3 (Standard, 4. Oktober 2017, 02:55:45)
[GCC 5.4.0 20160609] unter Linux
Gunicorn (Version 19.7.1)

Ich traf mit der Mühe.

Direkt nach dem Starten der App funktioniert es. Aber nur wenn eine Anfrage vorliegt, wird [CRITICAL] WORKER TIMEOUT ausgelöst. Zum Beispiel,

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

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

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

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

Als ich die Arbeiterklasse auf eventlet umgestellt habe, heißt das:
gunicorn --worker-class eventlet --log-level debug --bind 0.0.0.0:8080 app ,
Es ist in Ordnung.

Hinweis: Meine App läuft auf dem physischen Host, weder auf dem virtuellen Host noch auf dem Cloud-Host.


Aktualisieren:

Ich vermute also, es ist die Frage von Gevent oder Gevent Worker.

Es gibt Berichte zu dieser Ausgabe von gevent, die das Problem lösen und gevent das Problem verursachen. Ich kann hier keine Ursache identifizieren. Einige der Berichte können mit #1194 identisch sein, andere jedoch nicht.

Wenn jemand einen minimalen Fall zum Reproduzieren teilen kann, würde das helfen.

Ich bin mir nicht sicher, ob es definitiv das gleiche Problem ist, aber ich kann dies zu 100% mit Virtualbox mit dem folgenden Setup reproduzieren:

Host: Windows 10
Gast: Ubuntu 16.04
Gunicorn: 19.7.1

Ich leite TCP:8000 zwischen Host und Gast über die Standard-NAT-Verbindung weiter. Wenn ich einen sync Worker verwende, führen alle Anfragen an den Host für localhost:8000 dass diese Fehler im Protokoll erscheinen, aber wenn ich die gleichen Anfragen an den Gast stelle, ist das Protokoll klar. Wenn Sie zu --worker-class eventlet wechseln, wird der Trace entfernt.

Ich schätze, dass Virtualbox eine völlig andere Dimension ist, aber es klingt sehr ähnlich wie oben beschrieben und ist durchweg reproduzierbar (zumindest für mich).

Ich sehe dies bei langsamen Uploads. Wenn während eines Uploads (auf eine Django-Site) das Worker-Timeout erreicht wird, wird der Upload abgebrochen.

@lordmauve, wenn Sie den erwarteten Sync-Worker verwenden. Lange Anfragen werden den Arbeiter blockieren und schließlich wird der Arbiter ihn töten. Sie können einen anderen Worker-Typ verwenden, wenn Sie erwarten, dass lange Anforderungen erfolgreich sind.

Für alle, die diesen Thread lesen, öffnen Sie ihn bitte mit einem minimalen Fall, um ihn zu reproduzieren. Ich kann hier keine saubere Untersuchung sehen. Im Fall von AWS / ECS lasse ich #1194 noch offen, bis ich die von mir aufgelisteten Konfigurationen testen kann (https://github.com/benoitc/gunicorn/issues/1194#issuecomment-371250650).

Falls dieses Problem weiterhin besteht, überprüfen Sie bitte die Ressourcenverfügbarkeit für die Anwendung, erhöhen Sie zusätzlich das Timeout und ändern Sie den Worker-Klassentyp

Ich hatte dieses Problem, als ich versuche, meine Anwendung mit Docker Swarm bereitzustellen, und habe festgestellt, dass ich die Ressource für die Anwendung zu niedrig begrenzt habe. Die Erhöhung der Ressource löst das Problem für mich

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

Ich denke, das ist kein Fehler, sondern nur die Art und Weise, wie wir unsere Apps konfigurieren

@jseaidou es ist ein normales Timeout in dem Sinne, dass der Schiedsrichter darauf reagiert. Es ist kritisch, weil es normalerweise nicht passieren sollte.

Höchstwahrscheinlich führt einer Ihrer Mitarbeiter eine Blockierungsoperation durch, die den Gunicorn-Mitarbeiter daran hindert, den Schiedsrichter zu benachrichtigen. Wenn Sie eine lange Operation haben, stellen Sie sicher, dass Sie den geven-Scheduler von Zeit zu Zeit durch Schlafen oder ähnliches auslösen. oder alles, was auch den Tornado-Scheduler zurückruft.

Wie kann ich das Problem reproduzieren?

@saabeilin gleich ^^

Danke, das macht Sinn.
Für mich geschieht dies beim Bereitstellen einer großen Datei, die zuvor aus dem Cloud-Speicher heruntergeladen wurde.
Auf Anfrage wird die Datei aus dem Cloud-Speicher auf die lokale Festplatte abgerufen und dann an den Client stream-entschlüsselt. Der Download aus dem Cloud-Speicher funktioniert einwandfrei, auch wenn er 10 Minuten oder länger dauert.
Sobald der Worker mit der Stream-Entschlüsselung der Datei von der Festplatte zum Client beginnt, stirbt sie nach einigen hundert MB, wahrscheinlich weil sie bei dieser Blockierungsoperation eine Zeitüberschreitung hat.

War diese Seite hilfreich?
0 / 5 - 0 Bewertungen