Gunicorn: WAKTU PEKERJA KRITIS saat menjalankan aplikasi Flask

Dibuat pada 5 Jun 2018  ·  82Komentar  ·  Sumber: benoitc/gunicorn

Sepertinya sudah ada beberapa laporan yang terkait dengan kesalahan [CRITICAL] WORKER TIMEOUT tetapi terus bermunculan. Inilah masalah saya.

Saya menjalankan aplikasi Flask hello world ini.

from flask import Flask
application = Flask(__name__)

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

Perintah gunicorn adalah yang ini:

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

Dan ini adalah output konsol:

[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

Bisakah Anda menjelaskan dengan jelas mengapa saya mendapatkan kesalahan dan jika itu diharapkan dalam contoh ini? Bagaimana cara memperbaikinya atau jika itu adalah perilaku yang diharapkan mengapa kesalahan kritis?

Investigation unconfirmed

Komentar yang paling membantu

Menggunakan gunicorn dengan gevent tidak memperbaiki bug.

Semua 82 komentar

Kesalahan tidak diharapkan, tetapi tidak ada dari contoh Anda yang menunjukkan mengapa itu terjadi. Ceritakan lebih banyak tentang lingkungan Anda.

  • Klien apa yang digunakan untuk terhubung ke Gunicorn?
  • Proxy terbalik apa, jika ada, yang digunakan untuk menyambung ke Gunicorn?

Ceritakan lebih banyak tentang lingkungan Anda.

  • Klien apa yang digunakan untuk terhubung ke Gunicorn?
    => Saya baru saja mengirim permintaan dari Chromium: http://localhost :5000/
  • Proxy terbalik apa, jika ada, yang digunakan untuk menyambung ke Gunicorn?
    => Tanpa proxy, hanya Gunicorn + Flask

Saya baru saja mereproduksi masalah pada pengaturan yang benar-benar baru, berikut langkah-langkahnya:

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 adalah aplikasi Flask yang sama persis dengan yang saya posting di laporan awal.
Di bawah ini adalah log lengkapnya.

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

@bigunya Saya pikir itu karena batas waktu default, pekerja Anda telah diam selama 30-an. http://docs.gunicorn.org/en/stable/settings.html#timeout

Dari catatan Anda,

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

Saya melihat hal yang sama: pekerja kehabisan waktu bahkan ketika tidak melayani permintaan, dengan pekerja sinkronisasi.
Untuk itu, log level kritis cukup membingungkan.

Coba gunakan pekerja Gevent yang bisa menyelesaikan ini.

Untuk itu, log level kritis cukup membingungkan.

Tepat, itu adalah pertanyaan awal saya: jika itu adalah perilaku yang diharapkan, mengapa kesalahan kritis?
Akan menyenangkan juga untuk mendapatkan beberapa latar belakang mengapa pekerja perlu di-restart, mungkin ini bisa ditambahkan ke dokumen Desain .

Saya melihat ini juga (direproduksi dengan menggunakan examples/test.py dengan gunicorn test:app -b localhost:9595 --log-level=debug --timeout=5 ) dan saya setuju bahwa level kritis agak membingungkan. Saya akan baik-baik saja mengubahnya ke level debug. @benoitc @tilgovi bagaimana menurutmu?

Saya pikir level info mungkin sedikit lebih baik.

Saya memiliki hal yang sama dengan MSYS2 di Win10 tetapi akhirnya bisa diselesaikan.

di notify() dari ...\gunicorn\workers\workertmp.py, os.fchmod digunakan pada awalnya. Tapi itu tidak bekerja di MSYS. Alih-alih os.fchmod, saya menggunakan os.utime. Kode diikuti. Saya pikir itu bisa bekerja untuk semua platform.

    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 Saya tidak berharap pekerja keluar karena tidak ada permintaan yang terjadi. Kesalahan ini hanya akan terjadi jika pekerja tetap sibuk selama beberapa waktu > hingga batas waktu. Jadi kesalahannya kritis. Imo kami harus meningkatkan dokumentasi untuk memberikan lebih banyak kasus penggunaan dan tanggapan terhadap kesalahan tersebut.

Jika kesalahan masih terjadi saat pekerja tidak sibuk maka ada hal lain yang terjadi dan kami mungkin memiliki bug.

[EDIT]
Bug yang sama untuk saya.
Dengan Django 1.10 / gunicorn 19.6.0 / Python 2.7.15 di python2.7-alpine pada Debian 8.8 dan stock kernel 3.16, semuanya bekerja dengan baik.
Setelah memperbarui ke Django 1.11 dan gunicorn 19.8.1, para pekerja tetap gagal saat boot dengan [BATAS PEKERJA KRITIS].
Menurunkan versi gunicorn ke 19.6.0 tidak menyelesaikan masalah.
Kami memperbarui kernel host ke 4.9.0 (sudah dijadwalkan), dan para pekerja berhasil melakukan booting tanpa kesalahan.
Tetapi:

  • kami menggunakan 4 pekerja
  • setelah tepat 4 panggilan ke aplikasi Django, panggilan berikutnya akan habis, menunjukkan [BATAS PEKERJA KRITIS] di log
  • perintah top linux menunjukkan 4 proses gunicorn macet dengan konsumsi CPU yang cukup tinggi.

Kami akan mencoba gunicorn gevent untuk melihat apakah kami dapat membuat aplikasi kami kembali online.

Menggunakan gunicorn dengan gevent tidak memperbaiki bug.

ada pembaruan tentang masalah ini?

Sepertinya @neocolor mengidentifikasi bug nyata di bawah MSYS. Mungkin layak mendapat masalah terpisah.

@bigunya platform apa yang Anda jalankan? Saya telah mencoba mereproduksi dengan contoh sederhana dan saya tidak dapat melakukannya dengan mengikuti langkah-langkah yang dijelaskan di atas. Ini sesuai dengan pengalaman saya menjalankan banyak aplikasi dalam produksi pada banyak kerangka kerja. Sistem pemberitahuan pekerja tidak berubah baru-baru ini, sepengetahuan saya. Platform saya adalah Python 3.7 di MacOS 10.13.6, tetapi saya menjalankan Gunicorn dalam produksi dengan pekerja sinkronisasi untuk beberapa aplikasi di Python 2.7 dan 3.6.5 dan hanya melihat batas waktu pekerja ketika ada permintaan panjang yang sah yang memblokir pekerja.

Untuk @Tberdy : apa yang terjadi jika Anda mencoba mengatur --worker-tmp-dir ke suatu tempat di luar sistem file tmpfs? Saya hanya ingin tahu apakah mungkin alpine atau buruh pelabuhan atau kombinasinya entah bagaimana mengganggu cara pekerja memberi tahu arbiter.

Lihat juga #1388 untuk masalah tmpfs terkait Docker.

saya punya masalah ini.

Saya memiliki masalah ini juga, sinkronisasi gunicorn bekerja dengan sangat baik sampai kemarin, tetapi mulai melaporkan, batas waktu pekerja [KRITIS] menggunakan gevent tampaknya menyelesaikan masalah saya, tetapi saya benar-benar ingin tahu mengapa ini terjadi.

@timoj58 @cjmash dapatkah Anda memberikan detail lebih lanjut tentang masalah ini? Bagaimana Anda menjalankan gunicorn (dalam vm?, opsi ...), sistem file mana, OS? Sesuatu yang dapat membantu untuk mereproduksi akan sangat membantu :)

@benoitc Saya menjalankan gunicorn untuk memulai proyek Django saya di kubernetes argumen gunicorn saya adalah --bind=$port --workers=7 --timeout=1200 --log-level=debug --access-logfile - error-logfile - "

kesalahan yang saya dapatkan dari log

```E [2018-08-09 21:47:56 +0000] [13] [INFO] Boot pekerja dengan pid: 13

E [2018-08-09 21:47:56 +0000] [14] [INFO] Boot pekerja dengan pid: 14

E [2018-08-09 21:47:56 +0000] [12] [INFO] Boot pekerja dengan pid: 12

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

E [2018-08-09 21:47:56 +0000] [11] [INFO] Boot pekerja dengan pid: 11

E [2018-08-09 21:47:55 +0000] [10] [INFO] Boot pekerja dengan pid: 10

E [2018-08-09 21:47:55 +0000] [9] [INFO] Boot pekerja dengan pid: 9

E [2018-08-09 21:47:55 +0000] [8] [INFO] Boot pekerja dengan pid: 8

E [2018-08-09 21:47:55 +0000] [1] [INFO] Menggunakan pekerja: sinkronisasi

E [2018-08-09 21:47:55 +0000] [1] [INFO] Mendengarkan di: http://0.0.0.0 :4040 (1)

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

E [2018-08-09 21:47:55 +0000] [1] [INFO] Memulai gunicorn 19.7.1

E raw_paste_global_conf: []

Sandi E: TLSv1

E do_handshake_on_connect: Salah

E suppress_ragged_eofs: Benar

E ca_certs: Tidak ada

E cert_reqs: 0

E ssl_version: 2

E sertifikat: Tidak ada

File kunci E: Tidak ada

E proxy_allow_ips: ['127.0.0.1']

E proxy_protocol: Salah

E saat_keluar:

E nworkers_changed:

E pekerja_keluar:

E anak_keluar:

E post_request:

E pra_permintaan:

E pra_exec:

Pembatalan_pekerja:

E pekerja_int:

E post_worker_init:

E post_fork:

E pre_fork:

E kapan_siap:

E on_reload:

E on_starting:

E pasta: Tidak ada

E pythonpath: Tidak ada

E default_proc_name: art.wsgi

E proc_name: Tidak ada

E statsd_prefix:

E statsd_host: Tidak ada

E enable_stdio_inheritance: Salah

E syslog_facility: pengguna

E syslog_prefix: Tidak ada

E syslog: Salah

E syslog_addr: udp://localhost :514

E logconfig: Tidak ada

E logger_class: gunicorn.glogging.Logger

E capture_output: Salah

E loglevel: debug

E kesalahan log: -

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

E akses log: -

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: Tidak ada

E initgroups: Salah

E umask: 0

Grup E: 0

Pengguna E: 0

E worker_tmp_dir: Tidak ada

E pidfile: Tidak ada

E raw_env: []

E daemon: Salah

E chdir: /usr/src/app

E sendfile: Tidak ada

E preload_app: Salah

E check_config: Salah

E memuntahkan: Salah

E reload_engine: otomatis

E isi ulang: Salah

E limit_request_field_size: 8190

E limit_request_fields: 100

E limit_request_line: 4094

E tetap hidup: 2

E graceful_timeout: 30

E batas waktu: 1200

E max_requests_jitter: 0

E max_requests: 0

E pekerja_koneksi: 1000

E benang: 1

E worker_class: sinkronisasi

E pekerja: 7

Tumpukan E: 2048

E mengikat: ['0.0.0.0:4040']

Konfigurasi E: Tidak ada

E [2018-08-09 21:47:55 +0000] [1] [DEBUG] Konfigurasi saat ini:

I Tidak ada migrasi untuk diterapkan.

I Menjalankan migrasi:

Saya Menerapkan semua migrasi: admin, auth, tipe konten, inti, dasbor, jet, oauth2_provider, sesi

I Operasi yang harus dilakukan:

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

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

E /usr/src/app/art/wsgi.py:19: UserWarning: Tidak membaca /usr/src/app/.env - tidak ada.

E [2018-08-09 21:47:00 +0000] [21] [INFO] Boot pekerja dengan pid: 21

E [2018-08-09 21:47:00 +0000] [1] [INFO] Penanganan sinyal: term

E [2018-08-09 21:46:35 +0000] [12] [INFO] Boot pekerja dengan pid: 12

E [2018-08-09 21:46:34 +0000] [13] [INFO] Boot pekerja dengan pid: 13

E [2018-08-09 21:46:34 +0000] [11] [INFO] Boot pekerja dengan pid: 11

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

E [2018-08-09 21:46:34 +0000] [10] [INFO] Boot pekerja dengan pid: 10

E [2018-08-09 21:46:34 +0000] [9] [INFO] Boot pekerja dengan pid: 9

E [2018-08-09 21:46:34 +0000] [8] [INFO] Boot pekerja dengan pid: 8

E [2018-08-09 21:46:34 +0000] [7] [INFO] Boot pekerja dengan pid: 7

E [2018-08-09 21:46:34 +0000] [1] [INFO] Menggunakan pekerja: sinkronisasi

E [2018-08-09 21:46:34 +0000] [1] [INFO] Mendengarkan di: http://0.0.0.0 :4040 (1)

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

E [2018-08-09 21:46:34 +0000] [1] [INFO] Memulai gunicorn 19.7.1

E raw_paste_global_conf: []

Sandi E: TLSv1

E do_handshake_on_connect: Salah

E suppress_ragged_eofs: Benar

E ca_certs: Tidak ada

E cert_reqs: 0

E ssl_version: 2

E sertifikat: Tidak ada

File kunci E: Tidak ada

E proxy_allow_ips: ['127.0.0.1']

E proxy_protocol: Salah

E saat_keluar:

E nworkers_changed:

E pekerja_keluar:

E anak_keluar:

E post_request:

E pra_permintaan:

E pra_exec:

Pembatalan_pekerja:

E pekerja_int:

E post_worker_init:

E post_fork:

E pre_fork:

E kapan_siap:

E on_reload:

E on_starting:

E pasta: Tidak ada

E pythonpath: Tidak ada

E default_proc_name: art.wsgi

E proc_name: Tidak ada

E statsd_prefix:

E statsd_host: Tidak ada

E enable_stdio_inheritance: Salah

E syslog_facility: pengguna

E syslog_prefix: Tidak ada

E syslog: Salah

E syslog_addr: udp://localhost :514

E logconfig: Tidak ada

E logger_class: gunicorn.glogging.Logger

E capture_output: Salah

E loglevel: debug

E kesalahan log: -

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

E akses log: -

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: Tidak ada

E initgroups: Salah

E umask: 0

Grup E: 0

Pengguna E: 0

E worker_tmp_dir: Tidak ada

E pidfile: Tidak ada

E raw_env: []

E daemon: Salah

E chdir: /usr/src/app

E sendfile: Tidak ada

E preload_app: Salah

E check_config: Salah

E memuntahkan: Salah

E reload_engine: otomatis

E isi ulang: Salah

E limit_request_field_size: 8190

E limit_request_fields: 100

E limit_request_line: 4094

E tetap hidup: 2

E graceful_timeout: 30

E batas waktu: 1200

E max_requests_jitter: 0

E max_requests: 0

E pekerja_koneksi: 1000

E benang: 1

E worker_class: sinkronisasi

E pekerja: 7

Tumpukan E: 2048

E mengikat: ['0.0.0.0:4040']

Konfigurasi E: Tidak ada

E [2018-08-09 21:46:34 +0000] [1] [DEBUG] Konfigurasi saat ini:

```

Saya berjuang sedikit untuk mereproduksi masalah kali ini tetapi masih ada di versi terbaru gunicorn 19.9.0.
Langkah-langkah untuk mereproduksinya persis sama seperti yang saya jelaskan di posting ini .
Sistem saya adalah Arch Linux x86_64 GNU/Linux (kernel 4.17.2-1-ARCH), Python 3.6.5
Berikut adalah jejak log baru.

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

Seperti sebelumnya untuk mengujinya, saya hanya menekan http://0.0.0.0 :5000/ di Chromium.
Di bawah ini adalah konten Pipfile dan Pipfile.lock agar Anda dapat melihat lingkungan yang tepat.

  • 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": {}
}

Sekedar informasi, saya juga sering melihat kegagalan ini dengan:

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

Saya hanya punya wsgi.py yang memiliki

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

Beri tahu saya jika ada sesuatu yang Anda ingin saya coba/eksperimen atau jika ada spesifik dalam log yang Anda ingin saya periksa. Saya menjalankan flask pada VM GCP.

maaf karena terlambat membalas. Saya menjalankannya sebagai

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

saya memang menggunakan pengaturan gevent dll, tetapi saya telah mengubah desain saya tentang apa yang saya butuhkan ini untuk mengatasi masalah, maka pengaturan dasar di atas (yang juga gagal tetapi ini diharapkan karena tidak ada gevent)

Python versi 3.6
env: aws tensorflow_p36 dioptimalkan (ubuntu)
nginx berada di depan gunicorn, yang menjalankan aplikasi flask.

labu versi 1.0.2
nginx versi 1.10.3
gunicorn versi 19.9.0

Saya memang mengubah batas waktu nginx juga jika ini yang menyebabkannya.

Menghadapi masalah yang sama dengan server gunicorn

# gunicorn Applicat ionServer:app -b 0.0.0.0:6001 -w 8 --threads 4 --backlog 2048 \
# --timeout 120 --graceful-timeout 60 --access-logfile logs/access.log \

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

Labu == 0.12.1
gunicorn==19.7.1

ketika saya memulai server dengan perintah di atas, sistem saya membeku untuk beberapa waktu dan pid pekerja terus boot, meskipun saya mempertahankan batas waktu 120 detik, dan server tidak menerima satu permintaan.

Setiap pembaruan tentang masalah ini? Saya memiliki masalah yang sama

[KRITIS] WAKTU PEKERJA

Ingin tahu apakah ada yang berhasil mereproduksi ini dalam gambar Docker?

Juga melihat ini ketika mencoba mengimplementasikan pekerja ddtrace-run datadog pada aplikasi yang ada dimulai dengan gunicorn -k gevent --threads 4.

Jejak lucu dari SystemExit yang belum pernah saya lihat sebelumnya juga...
[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

Saya dapat mengatasi masalah ini dengan mencocokkan jumlah pekerja dan jumlah utas.

Saya telah menetapkan workers = (2 * cpu_count) + 1 dan tidak mengatur utas.

Setelah saya mengubah threads = workers , semuanya mulai berfungsi dengan baik. Untuk jaga-jaga, jika ini membantu seseorang.

Begini tampilannya sekarang

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

Saya mengalami masalah ini saat menjalankan Django dengan wadah Docker tunggal di AWS Elastic Beanstalk. Saya menyelesaikan masalah dengan memperbaiki grup keamanan saya untuk memastikan instans EC2 saya dapat berbicara dengan instans RDS saya. Saya menyadari ini mungkin bukan solusi untuk 99% orang tentang masalah ini, tetapi saya meninggalkan catatan ini untuk membantu orang lain menghindari membuang waktu berjam-jam jatuh ke lubang kelinci ini.

Dalam kasus saya, masalah diselesaikan dengan melakukan systemctl daemon-reload .
Singkat cerita saya tahu batas waktu default pada 30 detik, tetapi tidak dapat mengubahnya sampai saya pikir saya harus memuat ulang daemon systemd untuk menerapkan perubahan ke layanan.

@bigunyak @benoitc @tilgovi
Setelah pengejaran angsa google yang panjang dan beberapa eksperimen, saya yakin akar penyebab masalah ini adalah "layanan prakoneksi/prediksi" chrome (yang diaktifkan secara default di Chrome dan Chromium).

@jeiting menulis dengan baik tentang masalah ini
https://hackernoon.com/chrome-preconnect-breaks-singly-threaded-servers-95944be16400
Beberapa bacaan tambahan:
https://github.com/corydolphin/flask-cors/issues/147
https://github.com/pallets/flask/issues/2169

TLDR
Dalam beberapa kasus, Chrome/Chromium membuka dan menahan koneksi TCP "kosong" (yaitu memprediksi bahwa itu akan segera mengambil sumber daya lain). Jika koneksi TCP "kosong" mengenai server gunicorn Anda terlebih dahulu, maka permintaan "asli" berikutnya dari chrome dapat terhenti di belakang permintaan "kosong" hingga pekerja yang menangani permintaan "kosong" habis waktu. Ini lebih mungkin terjadi jika Anda hanya menjalankan satu pekerja sinkronisasi di gunicorn. Tetapi seperti yang ditemukan oleh eksperimen saya, itu bisa terjadi bahkan jika Anda menjalankan beberapa pekerja sinkronisasi.

Lingkunganku

  • OS asli saya adalah Ubuntu 17
  • Saya memiliki API istirahat yang berjalan di wadah buruh pelabuhan lokal. Baris yang relevan dari 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
......
  • Saya telah menginstal 3 browser: Firefox 61.0.1, Chromium 67.0.3396.99, Chrome 70.0.3538.102
  • Saya memiliki aplikasi reaksi yang disajikan dari wadah buruh pelabuhan yang berbeda pada port yang berbeda
  • Aplikasi reaksi membuat permintaan CORS AJAX ke API saya (itu adalah permintaan CORS karena javascript disajikan di satu port localhost saat mengirim panggilan API ke port localhost lain)
  • Permintaan yang selalu "diblokir" dalam eksperimen saya adalah permintaan CORS OPTIONS (dipicu oleh browser untuk meminta izin untuk kemudian melakukan permintaan POST). Tampaknya logis bahwa browser akan mencoba membuat koneksi prediktif dengan panggilan OPTIONS karena kemungkinan akan menindaklanjuti dengan panggilan POST.

Percobaan 1
Konfigurasi Gunicorn: 1 pekerja sinkronisasi (batas waktu default 30 detik)

Firefox: Di hampir setiap pemuatan halaman reaksi, permintaan CORS OPTIONS diblokir selama 5 detik, dan kemudian berhasil.
Chromium: Pada SETIAP pemuatan halaman reaksi, permintaan CORS OPTIONS diblokir selama 1,5 menit!!!! dan kemudian berhasil.
Chromium (layanan prediksi dinonaktifkan): Semuanya dimuat dengan baik
Chrome: Semuanya dimuat dengan baik

Percobaan 2
Konfigurasi Gunicorn: 4 pekerja sinkronisasi (batas waktu default 30 detik)

Firefox: Semuanya dimuat dengan baik
Chromium: Pada setiap pemuatan halaman reaksi ke-3, permintaan CORS OPTIONS diblokir selama 30 detik dan kemudian berhasil.
Chromium (layanan prediksi dinonaktifkan): Semuanya dimuat dengan baik
Chrome: Semuanya dimuat dengan baik

Percobaan 3
Konfigurasi Gunicorn: 8 pekerja sinkronisasi (batas waktu default 30 detik)

Firefox: Semuanya dimuat dengan baik
Chromium: Semuanya dimuat dengan baik
Chrome: Semuanya dimuat dengan baik

Percobaan 4
Jalankan server dev flask dengan threaded=True

Firefox: Semuanya dimuat dengan baik
Chromium: Semuanya dimuat dengan baik
Chrome: Semuanya dimuat dengan baik

Ringkasan Eksperimen

  • Firefox tampaknya juga memiliki layanan prediksi, tetapi tampaknya lebih anggun. (Eksperimen 1)
  • Chromium tampaknya paling agresif dalam membuat koneksi "prediksi". Tampaknya meluncurkan hingga 3-4 koneksi "prediksi" selama permintaan OPSI (Eksperimen 1 dan 2)
  • Anehnya meskipun Chrome juga mengaktifkan layanan prediksi, itu tidak menyebabkan masalah apa pun dalam eksperimen apa pun (mungkin urutan atau jumlah koneksi "prediksi" berbeda dari Chromium)

Larutan
Dalam Produksi: Perbaikan termudah adalah meletakkan nginx di depan gunicorn. Jika Anda ingin memahami mengapa nginx memecahkan masalah ini, inilah artikel bagus yang menjelaskannya: https://www.brianstorti.com/the-role-of-a-reverse-proxy-to-protect-your-application-against -pelambatan-klien/

Di dev: Perbaikan termudah adalah menjalankan server flask dev dengan threaded=True . Atau Anda dapat menonaktifkan layanan prediksi di Chrome/Chromium.

peningkatan debug gunicorn
Untuk membantu men-debug masalah seperti ini di masa mendatang, sebaiknya tambahkan pernyataan log debug di sebelah panggilan select() dan accept() di pekerja sinkronisasi.
https://github.com/benoitc/gunicorn/blob/e974f30517261b2bc95cfb2017a8688f367c8bf3/gunicorn/workers/sync.py#L26
https://github.com/benoitc/gunicorn/blob/e974f30517261b2bc95cfb2017a8688f367c8bf3/gunicorn/workers/sync.py#L34
Ini akan menunjukkan bahwa seorang pekerja telah menerima koneksi TCP baru, tetapi tidak menerima data apa pun.

@asnisarenko super menulis, terima kasih. #1929 adalah kasus lain yang tidak biasa dari klien lambat yang menghasilkan gejala serupa di server utas tunggal - dalam hal ini, jabat tangan TLS ke port non-TLS terlihat seperti klien penulisan lambat, karena gagal mengirim header yang masuk akal dengan cepat .

Mungkin Gunicorn, untuk pekerja sinkronisasi utas tunggal akan membutuhkan beberapa merdu baru, penurunan klien yang agresif untuk klien yang gagal mengirim setidaknya baris tajuk permintaan pertama, jika tidak semua tajuk, dalam waktu yang wajar.

Jika ini terjadi di aplikasi Anda, Anda dapat menambahkan beberapa kode diagnostik sementara:

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)

Semoga ini akan mengungkapkan di mana aplikasi Anda hang.

Sebagai contoh, saya entah bagaimana berhasil import flask sebelum gevent.monkey.patch_all() dan Flask saya app._before_request_lock akhirnya menjadi kunci non-gevent (yaitu polos tidak ditambal threading.Lock ). Dalam kasus seperti itu, dua permintaan secara berurutan pada permulaan aplikasi akan menyebabkannya macet (permintaan kedua akan mengunci seluruh utas). Tapi ini adalah bug saya, dan bug Anda mungkin berbeda.

@asnisarenko Saya tidak yakin mengapa Anda mengalami hang. Anda benar-benar _tidak_ membutuhkan pekerja per koneksi, karena setiap pekerja dapat secara kooperatif menangani ribuan koneksi (selama kode penanganan tidak memonopoli CPU/mengunci seluruh utas). Secara khusus, jika browser menghentikan permintaan, itu berarti bahwa ketika gunicorn read() s dari soket, itu akan memblokir greenlet, tetapi karena read harus ditambal dengan monyet, itu akan menghasilkan greenlet lainnya.

@ikonst
Masalah ini berbicara tentang menjalankan gunicorn dengan konfigurasi default. Kelas pekerja default adalah sync http://docs.gunicorn.org/en/stable/settings.html#worker -class

sync pekerja menggunakan model pre-fork dan setiap pekerja memproses satu koneksi/permintaan TCP pada satu waktu.

Saya tidak tahu apa yang menyebabkan ini bagi saya, tetapi beralih dari tipe pekerja default sync ke eventlet menyelesaikan masalah:

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

Semoga berhasil.

Mungkin ini hanya akan membantu saya, tetapi karena saya membutuhkan waktu 7 jam untuk men-debug masalah ini di pihak saya (aplikasi Flask/Gunicorn berjalan di Docker pada EC2), jika saya dapat menyisihkan sakit kepala ini untuk beberapa orang, ini adalah kemenangan kecil.

Batas memori penampung yang terlalu rendah. kehabisan waktu tanpa (tampaknya) tanpa alasan.

Jika saya memiliki kebocoran memori di masa depan, saya akan mencoba untuk menempatkan batas memori yang lebih tinggi, tetapi untuk saat ini, tidak ada batasan yang akan dilakukan.

Terima kasih

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)

Anda sangat membantu saya. EH )))

Ke mana perginya metode trace_on_abort() ini? Dalam file kode aplikasi? Apakah perlu anotasi?

@mattg-vbt tambahkan ini ke awal aplikasi Anda saat Anda perlu men-debug, dan hapus setelah Anda selesai men-debug

@ikonst Saya menambahkan ini ke aplikasi saya, tetapi saya tidak melihatnya terkena. Saya mendapatkan batas waktu pekerja, tetapi metode ini tidak berhasil.

@mattg-vbt dapatkah Anda mencoba melakukan kill -ABRT $pid untuk melihat fungsi print_trace dipanggil? (idenya adalah Anda akan mendapatkan SIGABRT dari werkzeug ketika pekerja Anda kehabisan waktu, tetapi pertama-tama mari kita periksa apakah itu dipanggil sama sekali)

@asnisarenko untuk yang kurang paham di antara kita, bagaimana cara memperbarui procfile?

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

@SumNeuron
Jika Anda menggunakan pekerja gevent Anda (bukan pekerja sinkronisasi) maka Anda seharusnya tidak mengalami masalah ini. Jadi perintah yang Anda posting tampaknya baik-baik saja.

Saya mendapatkan masalah ini dengan pekerja gevent hanya setelah inisialisasi, yang agak mengganggu karena saya sedang memproses beberapa tugas sebelum meluncurkan aplikasi saya. Tapi saya menetapkan batas waktu yang tinggi untuk saat ini.
Saya telah memposting repo pengujian yang dapat direproduksi di sini: https://github.com/zamponotiropita/test-gunicorn-worker-timeout -> test_0 gagal, test_1 dan test_2 lulus

@zamponotiropita Apakah Anda mencoba melakukan ini per pekerja atau per aplikasi sebelum forking?

@ikonst silakan periksa file run run.sh , ini per pekerja. Masalahnya tidak muncul dengan pramuat, tetapi saya mengalami masalah saat menghubungkan ke database saat memuat, karena objek aplikasi (dan bersama-sama dengan koneksi database) disalin dan melewati proses saat forking -> database saya tidak bisa menangani koneksi master dan pekerja yang identik, dan saya tidak dapat menemukan solusi

Saya mengalami masalah serupa. Saya mencoba menghasilkan banyak data saat itu juga dengan Flask menggunakan
metode ini , dan gagal karena waktu pekerja habis setelah apa pun yang ditetapkan di --timeout kedaluwarsa. Contoh minimal untuk direproduksi:

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

Kemudian jalankan gunicorn --timeout 10 test_gunicorn_timeout:app dan ketika meminta localhost:8000 setelah 10 detik Anda mendapatkan
[CRITICAL] WORKER TIMEOUT .

Saya juga mencoba menjalankan dengan -k gevent dan -k eventlet dan tidak ada yang berubah.

Saya menggunakan windows 10 Pro. Dengan komposisi buruh pelabuhan
gunicorn app -b 0.0.0.0:8000 -k gevent
Bekerja untuk saya dengan menginstal gevent di wadah python saya
Bagaimana cara menginstal gevent

Kemudian jalankan gunicorn --timeout 10 test_gunicorn_timeout:app dan ketika meminta localhost:8000 setelah 10 detik Anda mendapatkan
[CRITICAL] WORKER TIMEOUT .

Saya juga mencoba menjalankan dengan -k gevent dan -k eventlet dan tidak ada yang berubah.

@ltskv

sudahkah Anda menemukan solusi untuk masalah TIMEOUT PEKERJA [KRITIS]?

Saya memiliki masalah serupa dengan titik akhir streaming labu yang saya coba gunakan di heroku (yang menggunakan gunicorn). Di sana, frontend proxy seharusnya menjaga koneksi tetap hidup selama beberapa data dikirim dalam 30 detik, tetapi tampaknya gunicorn hanya mematikan proses jika belum selesai dalam 30 detik meskipun masih berjalan dan menghasilkan data.

Dokumentasi gunicorn tidak sepenuhnya jelas bagi saya dalam hal ini. Untuk --timeout dikatakan bahwa Workers silent for more than this many seconds are killed and restarted. Tetapi tampaknya pekerja terbunuh setelah 30 detik meskipun mereka masih menghasilkan data?

Dokumentasi gunicorn tidak sepenuhnya jelas bagi saya dalam hal ini. Untuk --timeout dikatakan bahwa Pekerja yang diam selama lebih dari beberapa detik ini terbunuh dan dimulai kembali. Tetapi tampaknya pekerja terbunuh setelah 30 detik meskipun mereka masih menghasilkan data?

@kurt-hectic bahwa dokumentasi harus ditingkatkan. Dengan diam, yang kami maksud adalah diam dari perspektif proses arbiter, yang berkomunikasi dengan para pekerja melalui file sementara. Jika pekerja sibuk mengirim data, itu tidak memperbarui file itu. Dari sudut pandang arbiter, pekerja tersebut kehilangan detak jantungnya.

Lihat juga # 1974.

Menggunakan pekerja apa pun selain pekerja default, pekerja sinkron harus mengurangi masalah dengan streaming badan besar, karena pekerja lain akan mempercepat file sementara bahkan ketika mereka menangani permintaan.

@kurt-hectic Saya memeriksa ulang sekali lagi opsi -k gevent dan memasukkan sleep(0) antara iterasi generator dan itu benar-benar berfungsi untuk saya (saya tidak yakin mengapa itu tidak berfungsi pada saat itu Saya memposting pertanyaan itu).

--waktu habis=5

Ini adalah penyebab paling umum dari masalah ini.

Saya harap solusi saya dapat membantu Anda. Saya menemui masalah batas waktu pekerja kritis ini beberapa hari yang lalu dan mencoba beberapa solusi. Sekarang bekerja dengan baik.

Berikut pemahaman dan solusi saya:

  1. Coba preload di gunicorn

Gagal mem-boot pekerja karena perlu lebih banyak waktu untuk memuat paket, seperti backend tensorflow, untuk memulai layanan. Jadi ketika Anda mengalami waktu boot aplikasi yang lambat, coba aktifkan opsi pramuat di gunicorn (Lihat https://devcenter.heroku.com/articles/python-gunicorn#advanced-configuration).

gunicorn halo: aplikasi --preload

  1. Cobalah untuk meningkatkan batas waktu untuk gunicorn

Batas waktu default adalah 30 detik. Jika aplikasi Anda benar-benar membutuhkan banyak waktu untuk menyelesaikan api, tambah batas waktu.

gunicorn halo: aplikasi --batas waktu 10

Namun, dari sudut pandang saya, tidak masuk akal jika api membutuhkan lebih dari 1 menit untuk menyelesaikannya. Jika demikian, cobalah untuk membuat beberapa kemajuan dalam kode Anda.

  1. Jika Anda menggunakan k8s, Anda juga dapat mengatur timeoutSeconds untuk wadah/gambar Anda di yaml.

Saya menghadapi masalah yang sama hari ini. Dalam kasus saya, api membutuhkan waktu sekitar satu menit untuk menghitung data dan kembali ke klien, yang mengakibatkan kesalahan CRITICAL WORKER TIMEOUT. Saya menyelesaikannya dengan meningkatkan batas waktu untuk gunicorn menjadi lebih dari satu menit - berhasil, tidak melihat masalah kembali. Semoga ini membantu. Saya menggunakan uvicorn.workers.UvicornWorker.

Saya memperbaikinya dengan menambahkan pekerja tambahan ke gnuicorn:

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

Tidak tahu mengapa.

Mungkin Anda mengalami kebuntuan? Apakah aplikasi Anda membuat permintaan untuk dirinya sendiri?

Pada Minggu, 5 Januari 2020, 10:52 alpinechicken, [email protected] menulis:

Saya memperbaikinya dengan menambahkan pekerja tambahan ke gnuicorn:

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

Tidak tahu mengapa.


Anda menerima ini karena Anda berkomentar.
Balas email ini secara langsung, lihat di GitHub
, https://github.com/benoitc/gunicorn/issues/1801?email_source=notifications&email_token=AAAEQJVQRCW3C63EZJWIN5DQ4G3WTA5CNFSM4FDLD5PKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LDNMVX
atau berhenti berlangganan
https://github.com/notifications/unsubscribe-auth/AAAEQJXZM4NLK56DZMFSZALQ4G3WTANCNFSM4FDLD5PA
.

Ya, satu rute memanggil yang lain - apakah itu buruk?

Ini berarti Anda membutuhkan setidaknya dua pekerja jika tidak, server Anda akan
jalan buntu. Permintaan akan menunggu hingga server merespons yang kedua
permintaan (yang akan diantrekan).

Anda mendapatkan satu permintaan bersamaan per pekerja.

Pada Senin, 6 Januari 2020, 02:45 alpinechicken, [email protected] menulis:

Ya, satu rute memanggil yang lain - apakah itu buruk?


Anda menerima ini karena Anda berkomentar.
Balas email ini secara langsung, lihat di GitHub
https://github.com/benoitc/gunicorn/issues/1801?email_source=notifications&email_token=AAAEQJSFEFBBI6AMZJCM4C3Q4KLOJA5CNFSM4FDLD5PKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LENMVXHJKTLOIWWS
atau berhenti berlangganan
https://github.com/notifications/unsubscribe-auth/AAAEQJXTCPOFIZJU5PUPOODQ4KLOJANCNFSM4FDLD5PA
.

Ah itu masuk akal. Terima kasih!

Pada Selasa, 7 Januari 2020 pukul 06:23 bobf [email protected] menulis:

Ini berarti Anda membutuhkan setidaknya dua pekerja jika tidak, server Anda akan
jalan buntu. Permintaan akan menunggu hingga server merespons yang kedua
permintaan (yang akan diantrekan).

Anda mendapatkan satu permintaan bersamaan per pekerja.

Pada Senin, 6 Januari 2020, 02:45 alpinechicken, [email protected] menulis:

Ya, satu rute memanggil yang lain - apakah itu buruk?


Anda menerima ini karena Anda berkomentar.
Balas email ini secara langsung, lihat di GitHub
<
https://github.com/benoitc/gunicorn/issues/1801?email_source=notifications&email_token=AAAEQJSFEFBBI6AMZJCM4C3Q4KLOJA5CNFSM4FDLD5PKYY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LENMVXHJKT05
,
atau berhenti berlangganan
<
https://github.com/notifications/unsubscribe-auth/AAAEQJXTCPOFIZJU5PUPOODQ4KLOJANCNFSM4FDLD5PA

.


Anda menerima ini karena Anda berkomentar.
Balas email ini secara langsung, lihat di GitHub
Https://github.com/benoitc/gunicorn/issues/1801?email_source=notifications&email_token=AAH2WRPVPVO2EJ53BKQW5B3Q4OHLRA5CNFSM4FDLD5PKYY3PNVWWK3TUL52HS4DFVREXG43VMVBZQ12GDN5VJW57ZQEILODN5VMXH2990issue
atau berhenti berlangganan
https://github.com/notifications/unsubscribe-auth/AAH2WRM2LLIB4O6OHCU5UG3Q4OHLRANCNFSM4FDLD5PA
.

pekerja_kelas', 'sinkronisasi')

Saya dapat mengatasi masalah ini dengan mencocokkan jumlah pekerja dan jumlah utas.

Saya telah menetapkan workers = (2 * cpu_count) + 1 dan tidak mengatur utas.

Setelah saya mengubah threads = workers , semuanya mulai berfungsi dengan baik. Untuk jaga-jaga, jika ini membantu seseorang.

Begini tampilannya sekarang

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

Sesuai dokumen gunicorn, itu mengubah kelas pekerja dari sinkronisasi ke gthread jika lebih dari satu utas disebutkan.
PS:-
Jika Anda mencoba menggunakan jenis pekerja sinkronisasi dan menyetel setelan utas ke lebih dari 1, jenis pekerja gthread akan digunakan sebagai gantinya.

kasus saya:

Lingkungan: Ubuntu18.04+ gunicorn+ nginx +flask

pip install gunicorn[gevent] di lingkungan virtual saya

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

Berhasil.

Terima kasih kepada semua orang di sini yang telah melakukan begitu banyak untuk membantu satu sama lain menyelesaikan masalah mereka. Silakan lanjutkan posting untuk masalah ini jika tampaknya sesuai.

Namun, saya menutup masalah ini karena menurut saya tidak ada bug di Gunicorn di sini dan menurut saya tidak ada tindakan yang harus diambil, meskipun saya dengan senang hati akan membantu meninjau PR yang mencoba menambahkan dokumentasi untuk ini entah bagaimana atau meningkatkannya pesan log.

Tolong jangan salah paham dengan niat saya. Jika Anda mencurigai adanya bug di Gunicorn dan ingin melanjutkan diskusi, silakan lakukan. Sebaiknya, buka tiket baru dengan aplikasi contoh yang mereproduksi masalah Anda. Namun, pada titik ini, ada terlalu banyak masalah, resolusi, dan percakapan yang berbeda dalam masalah ini sehingga sulit dibaca.

Jika Anda menjalankan Gunicorn tanpa proxy terbalik buffering di depannya, Anda _akan_ mendapatkan batas waktu dengan default, sinkronkan pekerja untuk sejumlah alasan. Yang umum adalah:

  • klien lambat
  • Koneksi prakoneksi / ambil awal yang dibiarkan terbuka oleh browser dan proxy
  • Respons lama karena memanggil API eksternal atau melakukan banyak pekerjaan terikat CPU

Anda dapat beralih ke jenis pekerja asinkron atau berulir, atau Anda dapat menempatkan Gunicorn di belakang proxy terbalik buffering. Jika Anda mengetahui bahwa waktu tunggu Anda disebabkan oleh kode Anda sendiri yang membuat panggilan lambat ke API eksternal atau melakukan pekerjaan signifikan yang Anda harapkan, Anda dapat meningkatkan opsi --timeout .

Ini berarti Anda membutuhkan setidaknya dua pekerja jika tidak, server Anda akan menemui jalan buntu. Permintaan akan menunggu hingga server merespons permintaan kedua (yang akan diantrekan). Anda mendapatkan satu permintaan bersamaan per pekerja.

Pada Sen, 6 Jan 2020, 02:45 alpinechicken, @ . * > menulis: Ya, satu rute memanggil yang lain - apakah itu buruk?

Apakah ini kasusnya ketika memanggil fungsi 'redirect' sebagai nilai balik untuk sebuah rute?

Apakah ini kasusnya ketika memanggil fungsi 'redirect' sebagai nilai balik untuk sebuah rute?

Tidak. Pengalihan labu merespons dengan pengalihan HTTP dan pekerja kemudian bebas menerima permintaan baru. Klien membuat permintaan lain ketika melihat respons ini dan setiap kali pekerja siap akan menerima permintaan ini.

Saya memperbaikinya dengan menambahkan pekerja tambahan ke gnuicorn:

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

Tidak tahu mengapa.

Apakah ini terkait dengan komentar @anilpai sebelumnya di mana ia menetapkan workers=1 + (multiprocessing.cpu_count() * 2) .. ?

Saya memiliki masalah serupa dengan ini. Ternyata saya memiliki kesalahan di titik masuk saya ke aplikasi. Dari debugging, sepertinya saya pada dasarnya meluncurkan aplikasi flask dari gunicorn, yang pekerjanya kemudian memasuki loop koneksi tak terbatas yang habis setiap 30 detik.

Saya yakin ini tidak memengaruhi semua pengguna di atas, tetapi mungkin memengaruhi beberapa pengguna.

Dalam file module/wsgi.py saya yang saya jalankan dengan gunicorn module.wsgi saya miliki -

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

Padahal saya seharusnya sudah -

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

Pada dasarnya, Anda tidak ingin memanggil application.run() saat menggunakan gunicorn. __name__ bawah gunicorn tidak akan menjadi "__main__" , tetapi akan berada di Flask, jadi Anda masih dapat men-debug secara lokal.

Saya tidak dapat menemukan referensi untuk ini di dokumen gunicorn, tetapi dapat membayangkannya sebagai kasus kesalahan umum, jadi mungkin beberapa peringatan diperlukan.

Ini masih terjadi. Menambahkan --preload ke panggilan Gunicorn memperbaiki masalah bagi saya.

Apakah bug ini masih belum diperbaiki? Saya mengamati perilaku yang tepat ini.

Gunicorn mulai seperti ini di 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

Proses pekerja terus-menerus habis dan dimulai ulang:

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 adalah aplikasi Flask trival.

Apakah masalah ini ditutup sebagai Jangan Perbaiki?

Saya juga mengalami masalah yang sama

Tetapi setelah Debugging saya dapat menemukan bahwa ketika gunicorn memulai Aplikasi Django salah satu ketergantungan memakan waktu lebih lama dari waktu yang diharapkan, (Dalam kasus saya koneksi DB eksternal) yang membuat gunicron worker menjadi timeout

Ketika saya menyelesaikan masalah koneksi, masalah batas waktu juga teratasi ...

Ini bukan kasus saya. Saya menguji dengan jenis aplikasi "Halo, Dunia", tanpa ketergantungan. Jadi saya masih bingung dengan ini, tetapi sepertinya tidak mungkin untuk memiliki Gunicorn dengan utas yang berjalan lama. Proses pekerja dimulai ulang dan karenanya mematikan utas yang berjalan lama.

@leonbrag
Ini mungkin BUKAN bug gunicorn. Lihat komentar saya di atas di utas. Ini adalah efek samping dari browser yang mengirimkan koneksi TCP "diprediksi" kosong, dan menjalankan gunicorn hanya dengan beberapa pekerja sinkronisasi tanpa perlindungan dari koneksi TCP yang kosong.

Apakah ada arsitektur/desain referensi yang menunjukkan cara yang tepat untuk menyiapkan aplikasi labu Gunicorn dengan utas pekerja (permanen) yang panjang?

Jika ini bukan bug, maka ini tampaknya merupakan artefak atau batasan arsitektur/desain Gunicorn.

Mengapa pekerja sinkronisasi tidak berjalan selamanya dan menerima koneksi klien. Pekerja tersebut akan menutup soket sesuai kebutuhan, namun terus berjalan tanpa keluar (dan karenanya utas pekerja terus berjalan).

@leonbrag
Anda harus lebih spesifik tentang masalah apa yang ingin Anda pecahkan.

Masalah yang dibahas di utas ini terjadi di lingkungan pengembang dan solusi termudah adalah menambahkan lebih banyak pekerja sinkronisasi atau menggunakan pekerja berulir.

Jika Anda ingin menghindari masalah ini dalam penyiapan produksi, Anda dapat menggunakan pekerja gevent, atau Anda dapat meletakkan nginx di depan gunicorn.
Beberapa PaaS sudah meletakkan nginx di depan wadah buruh pelabuhan Anda, jadi Anda tidak perlu mengkhawatirkannya. Sekali lagi solusinya tergantung pada konteks dan detailnya.

Ini adalah bacaan yang bagus.
https://www.brianstorti.com/the-role-of-a-reverse-proxy-to-protect-your-application-against-slow-clients/

Anda dapat memeriksa halaman desain dari dokumentasi. Pekerja async adalah satu
cara untuk menjalankan tugas yang panjang.

Pada Sabtu 8 Agustus 2020 pukul 18:00 leonbrag [email protected] menulis:

Apakah ada arsitektur/desain referensi yang menunjukkan cara yang tepat untuk menyiapkan?
Aplikasi labu Gunicorn dengan utas pekerja (permanen) yang panjang?

Jika ini bukan bug, maka sepertinya itu adalah artefak atau batasan dari
Arsitektur/desain Gunicorn.

Mengapa pekerja sinkronisasi tidak berjalan selamanya dan menerima koneksi klien. Seperti
pekerja akan menutup soket sesuai kebutuhan, namun terus berjalan tanpa keluar
(dan karenanya utas pekerja terus berjalan).


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/benoitc/gunicorn/issues/1801#issuecomment-670944797 ,
atau berhenti berlangganan
https://github.com/notifications/unsubscribe-auth/AAADRIWRQGIP3R5PMVJ5ENTR7VZA3ANCNFSM4FDLD5PA
.

>

Dikirim dari Ponsel saya

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

Saya memperbaiki masalah saya dengan meningkatkan --timeout

Lihat juga #1388 untuk masalah tmpfs terkait Docker.

Oh, terima kasih banyak Randall, saya lupa menambahkan --worker-tmp-dir /dev/shm ke argumen gunicorn ketika saya menjalankan gunicorn di Docker.

BTW apakah 64 Mb cukup untuk cache gunicorn?

aplikasi gunicorn
Atau
aplikasi gunicorn

Bekerja untuk saya... Saya lebih suka timeout satu.

Aneh, saya menambahkan --worker-tmp-dir /dev/shm tetapi masih menerima:

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

Untuk memastikan /dev/shm adalah ramf, saya membandingkannya:

image

Param berikutnya:

    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: Saya menggunakan PyPy

@attajutt timeout bagus tetapi Anda mempertaruhkan bahwa proses master gunicorn akan mendeteksi hangup dalam proses pekerja Anda hanya setelah 1000 detik, dan Anda akan kehilangan banyak permintaan. Juga akan sulit untuk mendeteksinya jika hanya satu dari beberapa pekerja yang akan hangup. Saya tidak akan melakukan 1000 setidaknya.

@ivictbor terima kasih untuk lmk. 1000 adalah untuk referensi. Namun demikian, saya menjalankan aplikasi setelah dimuat Ini berjalan dengan baik.

Saya mendapatkan masalah kesalahan ini juga dan setelah beberapa kali, saya menemukan bahwa masalahnya mungkin disebabkan:

  1. Konfigurasi Nginx
  2. Gunicorn/Uwsgi

Jika Anda menerapkan aplikasi Anda di cloud seperti GAE, itu tidak akan memunculkan kesalahan petunjuk apa pun.
anda dapat mencoba memunculkan kesalahan menggunakan solusi kasus ini: https://stackoverflow.com/questions/38012797/google-app-engine-502-bad-gateway-with-nodejs

Jika mengangkat 502 gateway buruk;
mungkin akan memiliki 2 kemungkinan:

  1. gunicorn tidak berjalan
  2. gunicorn mendapat waktu habis

sulotion lengkap dijelaskan di sini: https://www.datadoghq.com/blog/nginx-502-bad-gateway-errors-gunicorn/

berharap dapat memperbaiki siapa pun yang mengalami kesalahan dalam [CRITICAL] WORKER TIMEOUT

Menambahkan kemungkinan lain bagi mereka yang menemukan utas ini ...

Ini juga dapat disebabkan oleh buruh pelabuhan yang memberlakukan batasan sumber daya yang terlalu rendah untuk aplikasi web Anda. Misalnya saya memiliki batasan berikut:

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

dan ini ternyata terlalu rendah untuk gunicorn jadi saya terus-menerus mendapatkan kesalahan [CRITICAL] WORKER TIMEOUT sampai saya menghapus batasannya.

Untuk gunicorn sumber daya ini baik-baik saja. Tapi Anda memang perlu
pesawat untuk jumlah pekerja dan sumber daya yang dibutuhkan untuk Anda
aplikasi. 128M dan 0.25cpu tampaknya sangat rendah untuk aplikasi web
ditulis dengan Python.... secara umum Anda membutuhkan setidaknya 1 inti /vcpu dan
512MB RAM sebagai minimal.

Pada Jum 26 Mar 2021 pukul 02:14, Colton Hicks @ . * > menulis:

Menambahkan kemungkinan lain bagi mereka yang menemukan utas ini ...

Ini juga dapat disebabkan oleh buruh pelabuhan yang memberlakukan batasan sumber daya yang
terlalu rendah untuk aplikasi web Anda. Misalnya saya punya yang berikut
kendala:

jasa:
aplikasi website:
gambar: bla-bla
menyebarkan:
sumber daya:
batas:
CPU: "0,25"
memori: 128M

dan ini ternyata terlalu rendah untuk gunicorn jadi saya terus-menerus mendapatkan [KRITIS]
WORKER TIMEOUT kesalahan sampai saya menghapus kendala.


Anda menerima ini karena Anda disebutkan.
Balas email ini secara langsung, lihat di GitHub
https://github.com/benoitc/gunicorn/issues/1801#issuecomment-807855647 ,
atau berhenti berlangganan
https://github.com/notifications/unsubscribe-auth/AAADRITPZB7BMA6QW7LFNVLTFPNV3ANCNFSM4FDLD5PA
.

>

Dikirim dari Ponsel saya

--timeout=1000 bekerja dari saya. Masalahnya adalah mesin GCP dengan sumber daya cpu rendah. Ini berfungsi dengan baik di mesin lokal saya dengan batas waktu default.

Apakah halaman ini membantu?
0 / 5 - 0 peringkat