Gunicorn: «Загрузочный рабочий» зацикливается бесконечно, несмотря на отсутствие сигналов выхода.

Созданный на 11 дек. 2017  ·  65Комментарии  ·  Источник: benoitc/gunicorn

Я пытаюсь настроить Gunicorn на Docker. Он хорошо работает локально, и производственный образ точно такой же, как и локальный образ, но я получаю такое странное поведение в производственном движке Docker:

ml-server_1     | [2017-12-11 13:18:50 +0000] [1] [INFO] Starting gunicorn 19.7.1
ml-server_1     | [2017-12-11 13:18:50 +0000] [1] [DEBUG] Arbiter booted
ml-server_1     | [2017-12-11 13:18:50 +0000] [1] [INFO] Listening at: http://0.0.0.0:80 (1)
ml-server_1     | [2017-12-11 13:18:50 +0000] [1] [INFO] Using worker: sync
ml-server_1     | [2017-12-11 13:18:50 +0000] [8] [INFO] Booting worker with pid: 8
ml-server_1     | [2017-12-11 13:18:50 +0000] [1] [DEBUG] 1 workers
ml-server_1     | Using TensorFlow backend.
ml-server_1     | [2017-12-11 13:18:54 +0000] [11] [INFO] Booting worker with pid: 11
ml-server_1     | Using TensorFlow backend.
ml-server_1     | [2017-12-11 13:18:58 +0000] [14] [INFO] Booting worker with pid: 14
ml-server_1     | Using TensorFlow backend.
ml-server_1     | [2017-12-11 13:19:02 +0000] [17] [INFO] Booting worker with pid: 17
ml-server_1     | Using TensorFlow backend.

Похоже, Gunicorn загружает рабочих каждые 4-5 секунд, несмотря на отсутствие явных сообщений об ошибках или сигналов выхода. Такое поведение продолжается бесконечно, пока не будет прекращено.

Возможно ли, что воркер может выйти, ничего не записывая в stderr / stdout, или чтобы арбитр мог бесконечно порождать воркеров?

Поскольку это один и тот же образ докера, они запускают один и тот же код на одной и той же архитектуре, поэтому я действительно не понимаю, что это может быть (ошибка?). Любая помощь очень ценится!

Improvement help wanted

Самый полезный комментарий

Просто обновление, проблема для меня на самом деле была ошибкой памяти и была исправлена, когда проблема с памятью была исправлена.

Все 65 Комментарий

ssh -ing в контейнер Docker заставил меня найти эту ошибку:

Illegal instruction (core dumped)

Может быть, Gunicorn следует выявлять подобные ошибки, а не глотать их, или обращаться с ними по-другому? Не уверен, просто подумал, что подниму это, потому что это может помочь кому-то другому!

Благодарим за сообщение о проблеме!

Если вы сможете выяснить, где это происходит, это будет очень полезно.

Возможно, мы сможем добавить логирование при выходе рабочих. Обычно сам воркер записывает в журнал, но если его очень резко убить, этого не произойдет.

Не стоит беспокоиться!

Кажется, проблема с Spacy, которую я только что добавил в эту ветку: https://github.com/explosion/spaCy/issues/1589

В любом случае, это вызывает SIGILL поскольку strace подтверждает:

--- SIGILL {si_signo=SIGILL, si_code=ILL_ILLOPN, si_addr=0x7ff48bbe6cea} ---
+++ killed by SIGILL (core dumped) +++
Illegal instruction (core dumped)

Я полагаю, было бы неплохо, если бы Gunicorn мог идентифицировать это и регистрировать ошибку, а не фантомно перезапускать воркера, но, черт возьми, я очень мало знаю о том, как работают коды выхода!

Некоторые коды выхода определенно имеют особое значение, и мы, вероятно, могли бы их зарегистрировать.
http://tldp.org/LDP/abs/html/exitcodes.html

Звучит отлично! Кроме того, если код выхода не является зарезервированным кодом выхода (как в этом случае), было бы здорово, если бы это можно было зарегистрировать (без объяснения причин), чтобы было очевидно, что рабочий процесс действительно завершает работу 🙂

У меня похожая проблема, Gunicorn всегда загружает нового рабочего, когда я делаю HTTP-запрос. Я не получаю никакого ответа, он просто всегда перезагружает нового рабочего. Журнал Strace из двух HTTP-запросов:

select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=510, si_uid=0, si_status=SIGSEGV, si_utime=160, si_stime=32} ---
getpid()                                = 495
rt_sigreturn({mask=[]})                 = -1 EINTR (Interrupted system call)
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGSEGV && WCOREDUMP(s)}], WNOHANG, NULL) = 510
lseek(8, 0, SEEK_CUR)                   = 0
close(8)                                = 0
wait4(-1, 0x7ffd455ad844, WNOHANG, NULL) = 0
write(4, ".", 1)                        = 1
select(4, [3], [], [], {0, 840340})     = 1 (in [3], left {0, 840338})
read(3, ".", 1)                         = 1
read(3, 0x7f2682025fa0, 1)              = -1 EAGAIN (Resource temporarily unavailable)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
umask(0)                                = 022
getpid()                                = 495
open("/tmp/wgunicorn-q4aa72u7", O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, 0600) = 8
fcntl(8, F_SETFD, FD_CLOEXEC)           = 0
chown("/tmp/wgunicorn-q4aa72u7", 0, 0)  = 0
umask(022)                              = 0
unlink("/tmp/wgunicorn-q4aa72u7")       = 0
fstat(8, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
ioctl(8, TIOCGWINSZ, 0x7ffd455b8e50)    = -1 ENOTTY (Not a tty)
lseek(8, 0, SEEK_CUR)                   = 0
lseek(8, 0, SEEK_CUR)                   = 0
rt_sigprocmask(SIG_BLOCK, ~[], [], 8)   = 0
fork()                                  = 558
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
select(0, NULL, NULL, NULL, {0, 37381}[2017-12-28 17:50:23 +0000] [558] [INFO] Booting worker with pid: 558
) = 0 (Timeout)
select(4, [3], [], [], {1, 0}loading test-eu-ovh settings
)          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0}
)          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG, st_size=0, ...}) = 0
select(4, [3], [], [], {1, 0})          = ? ERESTARTNOHAND (To be restarted if no handler)
--- SIGCHLD {si_signo=SIGCHLD, si_code=CLD_KILLED, si_pid=499, si_uid=0, si_status=SIGSEGV, si_utime=160, si_stime=31} ---
getpid()                                = 495
rt_sigreturn({mask=[]})                 = -1 EINTR (Interrupted system call)
wait4(-1, [{WIFSIGNALED(s) && WTERMSIG(s) == SIGSEGV && WCOREDUMP(s)}], WNOHANG, NULL) = 499
lseek(7, 0, SEEK_CUR)                   = 0
close(7)                                = 0
wait4(-1, 0x7ffd455ad844, WNOHANG, NULL) = 0
write(4, ".", 1)                        = 1
select(4, [3], [], [], {0, 450691})     = 1 (in [3], left {0, 450689})
read(3, ".", 1)                         = 1
read(3, 0x7f2682067de8, 1)              = -1 EAGAIN (Resource temporarily unavailable)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG, st_size=0, ...}) = 0
umask(0)                                = 022
getpid()                                = 495
open("/tmp/wgunicorn-5x9a40ca", O_RDWR|O_CREAT|O_EXCL|O_NOFOLLOW|O_CLOEXEC, 0600) = 7
fcntl(7, F_SETFD, FD_CLOEXEC)           = 0
chown("/tmp/wgunicorn-5x9a40ca", 0, 0)  = 0
umask(022)                              = 0
unlink("/tmp/wgunicorn-5x9a40ca")       = 0
fstat(7, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
ioctl(7, TIOCGWINSZ, 0x7ffd455b8e50)    = -1 ENOTTY (Not a tty)
lseek(7, 0, SEEK_CUR)                   = 0
lseek(7, 0, SEEK_CUR)                   = 0
rt_sigprocmask(SIG_BLOCK, ~[], [], 8)   = 0
fork()                                  = 579
rt_sigprocmask(SIG_SETMASK, [], NULL, 8) = 0
select(0, NULL, NULL, NULL, {0, 8144}[2017-12-28 17:50:30 +0000] [579] [INFO] Booting worker with pid: 579
)  = 0 (Timeout)
select(4, [3], [], [], {1, 0})          = 0 (Timeout)
fstat(6, {st_mode=S_IFREG, st_size=0, ...}) = 0
fstat(7, {st_mode=S_IFREG|0600, st_size=0, ...}) = 0
fstat(9, {st_mode=S_IFREG|01, st_size=0, ...}) = 0
fstat(8, {st_mode=S_IFREG|01, st_size=0, ...}) = 0

Я столкнулся с той же проблемой: gunicorn загружается повторно в течение нескольких секунд для рабочего типа sync . Установка тайм-аута рабочего на 900 не помогает.

В моей загрузке перед действием я загружаю данные из AWS S3. Загрузка различных файлов занимает около 1 минуты 10 секунд.

@ sara-02 какая у вас командная строка для запуска пулеметчика?

@benoitc gunicorn --pythonpath /src -b 0.0.0.0:$SERVICE_PORT --workers=1 -k sync -t $SERVICE_TIMEOUT flask_endpoint:app
Присутствовать здесь

@ sara-02 Спасибо.

Действительно ли старые рабочие уходят или они остаются в сети и появляются новые рабочие? Что также показывает журнал отладки?

Журналы смешаны с журналами ботокора, но это примерно так

[INFO] Booting worker with pid:  a
[INFO] Booting worker with pid:  b
[INFO] Booting worker with pid:  c

а рабочий убит? что вернуть команду ps ax|grep gunicorn ?

@benoitc
screenshot from 2018-07-05 19-14-00

Однако возникает вопрос: почему мы видим 2 процесса gunicorn , когда ограничение числа рабочих установлено равным 1? Один хозяин и один рабочий?

Есть 1 процесс-арбитр (мастер) и N рабочих процессов ye :)

Значит, вы запускаете команду каждый раз, когда рабочий загружается, верно? Если это так, кажется, что старый рабочий убит, создается новый. Я займусь расследованием.

@ sara-02 и последнее, это тоже происходит в докере?

@benoitc на docker-compose работает, как ожидалось, но когда я помещаю тот же код на Openshift , я вижу эту ошибку. Увеличение требований к памяти исправлено, но когда я запускаю приложение через docker-compose оно использует меньше limited памяти.

Просто обновление, проблема для меня на самом деле была ошибкой памяти и была исправлена, когда проблема с памятью была исправлена.

@benoitc
Я столкнулся с той же проблемой при попытке создать 5 рабочих-пулеметчиков в докере.
@ sara-02
Как вы определили причину ошибки памяти?

image

@ gulshan-gaurav мне помогли 2 вещи:
Я увеличил память, выделенную для моего пода, и перестал давать сбой. Во-вторых, мы проверили наши журналы Openshift Zabbix.

@ sara-02
Даже в моем промежуточном модуле файлы + модели, которые я загружаю в память, составляют 50 МБ, поэтому 2 ГБ памяти должно быть достаточно для 5 рабочих.

@ gulshan-gaurav, с какой проблемой вы столкнулись? Имея там 5 процессов выглядит хорошо ....

Я была такая же проблема. Я не обнаружил точной проблемы, но она была решена после того, как я обновил python 3.5 до 3.6.

Я столкнулся с той же проблемой в контейнере Docker. Gunicorn продолжает загружать нового воркера каждый раз, когда я вызываю конечную точку, которая вызывает сбой, но в файлы журнала Gunicorn не выводится исключение или ошибка. То, что я выбираю для печати, записывается в журнал, а затем внезапно в файле журнала просто говорится: «Загрузка рабочего с pid ...»

Один из шагов, который помог, заключался в добавлении переменной env PYTHONUNBUFFERED. До этого исчезли даже операторы печати, которые не сохранялись в журналах Gunicorn.

2 другие конечные точки приложения работают правильно.

Я запускаю Gunicorn с помощью: gunicorn run: app -b localhost: 5000 --enable-stdio-inheritance --error-logfile /var/log/gunicorn/error.log --access-logfile / var / log / gunicorn / access. log --capture-output --log-level отладка

Уже запущен Python 3.6 и проверил с помощью top, что память, похоже, не является проблемой.

РЕДАКТИРОВАТЬ: Похоже, это проблема Python, а не ошибка Gunicorn. Некоторые несоответствия версий приводили к тому, что Python просто бесследно умирал при выполнении определенной операции.

Я столкнулся с аналогичной проблемой, когда рабочий узел продолжает придумывать
Booting worker with pid: 17636 . Я не знаю, убивает ли он предыдущий рабочий узел или предыдущий рабочий узел все еще существует. Но количество рабочих, упомянутых в аргументах командной строки gunicorn, составляет всего 3 - -workers=3 . Также я использую Python версии 3.7.

У меня было несоответствие зависимости scikit-learn, но даже после его решения я получаю все те же бесконечные рабочие. какие расхождения в версиях Python мне следует искать и как их идентифицировать?

У меня такая же проблема внутри OpenShift.

image

Как вы можете видеть на изображении, я использую 6 воркеров (я пробовал с 3).
Я увеличил память пода, и он не работает.

BuildConfig:

image

Любая идея?

Спасибо

вы запускаете это в aws за elb? Я решил эту проблему, поместив nginx ingress между elb и gunicorn

Есть такая же проблема.

flask_1  | [2019-02-23 09:08:17 +0000] [1] [INFO] Starting gunicorn 19.9.0
flask_1  | [2019-02-23 09:08:17 +0000] [1] [INFO] Listening at: http://0.0.0.0:5000 (1)
flask_1  | [2019-02-23 09:08:17 +0000] [1] [INFO] Using worker: sync
flask_1  | [2019-02-23 09:08:17 +0000] [8] [INFO] Booting worker with pid: 8
flask_1  | [2019-02-23 09:08:19 +0000] [12] [INFO] Booting worker with pid: 12
flask_1  | [2019-02-23 09:08:19 +0000] [16] [INFO] Booting worker with pid: 16
flask_1  | [2019-02-23 09:08:20 +0000] [20] [INFO] Booting worker with pid: 20
flask_1  | [2019-02-23 09:08:21 +0000] [24] [INFO] Booting worker with pid: 24
flask_1  | [2019-02-23 09:08:22 +0000] [28] [INFO] Booting worker with pid: 28
flask_1  | [2019-02-23 09:08:23 +0000] [32] [INFO] Booting worker with pid: 32
flask_1  | [2019-02-23 09:08:25 +0000] [36] [INFO] Booting worker with pid: 36
flask_1  | [2019-02-23 09:08:26 +0000] [40] [INFO] Booting worker with pid: 40
flask_1  | [2019-02-23 09:08:27 +0000] [44] [INFO] Booting worker with pid: 44
flask_1  | [2019-02-23 09:08:29 +0000] [48] [INFO] Booting worker with pid: 48
flask_1  | [2019-02-23 09:08:30 +0000] [52] [INFO] Booting worker with pid: 52
flask_1  | [2019-02-23 09:08:31 +0000] [56] [INFO] Booting worker with pid: 56
flask_1  | [2019-02-23 09:08:33 +0000] [60] [INFO] Booting worker with pid: 60
flask_1  | [2019-02-23 09:08:34 +0000] [64] [INFO] Booting worker with pid: 64
flask_1  | [2019-02-23 09:08:35 +0000] [68] [INFO] Booting worker with pid: 68
flask_1  | [2019-02-23 09:08:36 +0000] [72] [INFO] Booting worker with pid: 72
flask_1  | [2019-02-23 09:08:37 +0000] [76] [INFO] Booting worker with pid: 76
flask_1  | [2019-02-23 09:08:38 +0000] [80] [INFO] Booting worker with pid: 80
flask_1  | [2019-02-23 09:08:40 +0000] [84] [INFO] Booting worker with pid: 84
flask_1  | [2019-02-23 09:08:41 +0000] [88] [INFO] Booting worker with pid: 88
flask_1  | [2019-02-23 09:08:42 +0000] [92] [INFO] Booting worker with pid: 92
flask_1  | [2019-02-23 09:08:44 +0000] [96] [INFO] Booting worker with pid: 96
flask_1  | [2019-02-23 09:08:45 +0000] [100] [INFO] Booting worker with pid: 100
flask_1  | [2019-02-23 09:08:45 +0000] [104] [INFO] Booting worker with pid: 104
flask_1  | [2019-02-23 09:08:46 +0000] [108] [INFO] Booting worker with pid: 108
flask_1  | [2019-02-23 09:08:47 +0000] [112] [INFO] Booting worker with pid: 112
flask_1  | [2019-02-23 09:08:48 +0000] [116] [INFO] Booting worker with pid: 116
flask_1  | [2019-02-23 09:08:49 +0000] [120] [INFO] Booting worker with pid: 120
flask_1  | [2019-02-23 09:08:50 +0000] [124] [INFO] Booting worker with pid: 124
flask_1  | [2019-02-23 09:08:52 +0000] [128] [INFO] Booting worker with pid: 128

Вот docker-compose.yml :

version: '3'
services:
  flask:
    build: .
    command: gunicorn -b 0.0.0.0:5000 hello:app --reload
    environment:
      - FLASK_APP=hello.py
      - FLASK_DEBUG=1
      - PYTHONUNBUFFERED=True
    ports:
      - "5000:5000"
    volumes:
      - ./:/root

какой образ докера он использует?

@benoitc

[ec2-user@ip-172-31-85-181 web-services-course]$ docker --version
Docker version 18.06.1-ce, build e68fc7a215d7133c34aa18e3b72b4a21fd0c6136
[ec2-user@ip-172-31-85-181 web-services-course]$ docker-compose --version
docker-compose version 1.23.2, build 1110ad01

Вот ссылки на:

понял, что это может быть вызвано нехваткой памяти. приложению требуется больше памяти, чем доступно.
но это просто предположение

Так же как информация: я наблюдал именно такое поведение, когда у меня был конфигурирован пулемет для 3 рабочих, но я развернул код на виртуальной машине с одноядерным процессором. Затем я меняю среду, чтобы использовать 2 ядра, и, очевидно, проблема исчезла.

Почему «Рабочий выходит» только на уровне ИНФОРМАЦИЯ - почему рабочий должен завершать работу, кроме как в результате ошибки? Мне потребовалось много времени, чтобы понять, что мои рабочие потоки были убиты системным убийцей OOM, и в журналах ничего не было, кроме, как сообщали некоторые другие выше, «Загрузка рабочего с pid» время от времени.

@HughWarrington, потому что выход рабочего не обязательно является ошибкой. Рабочие могут быть завершены сигналами или такими опциями, как --max-requests .

@HughWarrington, возможно, мы могли бы добавить логирование в арбитр, когда рабочий выходит с аномальным кодом выхода.

Вы можете открыть билет для этого или внести PR, который добавит этот код к методу reap_workers .

У меня была такая же проблема, и я решил увеличить объем памяти модуля.

Была такая же проблема с запуском Gunicorn на Docker с большой моделью spaCy, он продолжал перезапускать воркеры без каких-либо сообщений об ошибках. Решение - увеличить память для контейнера Docker.

Только что столкнулся с этой проблемой сегодня на последней версии (19.9.0) gunicorn с рабочими процессами gevent (1.4.0), работающими на Kubernetes. Это приложение Falcon , а образ Docker - это официальный образ Python с тегом 3.7.3 .

[2019-07-05 00:07:42 +0000] [8] [INFO] Starting gunicorn 19.9.0
[2019-07-05 00:07:42 +0000] [8] [INFO] Listening at: http://0.0.0.0:5000 (8)
[2019-07-05 00:07:42 +0000] [8] [INFO] Using worker: gevent
[2019-07-05 00:07:43 +0000] [35] [INFO] Booting worker with pid: 35
[2019-07-05 00:07:43 +0000] [36] [INFO] Booting worker with pid: 36
[2019-07-05 00:07:43 +0000] [37] [INFO] Booting worker with pid: 37
[2019-07-05 00:07:43 +0000] [38] [INFO] Booting worker with pid: 38
[2019-07-05 00:07:43 +0000] [41] [INFO] Booting worker with pid: 41
[2019-07-05 00:07:43 +0000] [43] [INFO] Booting worker with pid: 43
[2019-07-05 00:07:43 +0000] [45] [INFO] Booting worker with pid: 45
[2019-07-05 00:07:43 +0000] [49] [INFO] Booting worker with pid: 49
[2019-07-05 00:07:43 +0000] [47] [INFO] Booting worker with pid: 47
[2019-07-05 00:07:49 +0000] [53] [INFO] Booting worker with pid: 53
[2019-07-05 00:07:50 +0000] [54] [INFO] Booting worker with pid: 54
[2019-07-05 00:07:53 +0000] [57] [INFO] Booting worker with pid: 57
[...]

У модуля были следующие настройки ресурсов:

resources:
  requests:
    cpu: 250m
    memory: 256Mi
  limits:
    cpu: 500m
    memory: 512Mi

Удвоение всего устранило проблему.

Мы заметили одну интересную вещь: глядя на dmesg на хост-машине, мы можем видеть, что это segfault -ing в libcrypto при доступе к серверу с использованием SSL.

Память для меня не проблема, потому что я не загружаю в память какую-либо большую модель. Рабочие просто продолжают давать сбой, и я не вижу сообщений об ошибках. Это можно как-то исправить?

image

такая же проблема для меня, есть идеи исправить? Python 3.6.3 с Gunicorn 19.9.0

@MrKiven, что делает ваше приложение? вы используете такие вещи, как запрос?

может кто-нибудь предоставляет способ воспроизвести проблему?

Это менеджер нескольких компонентов, которые выполняются в конвейере. Некоторые из них могут запускать HTTP-запросы к другим компонентам на той же машине или на удаленных машинах. Некоторые модули конвейера могут выполняться параллельно, но они выполняются с помощью ThreadPoolExecutor. Они не используют никаких общих объектов, а только генерируют структуры данных, которые позже объединяются в единую результирующую.

К сожалению, я не уверен, что смогу собрать минимальный пример, не раскрывая нашу систему.

request делает много небезопасных вещей с потоками, которые иногда разветвляют новый процесс. Я бы посоветовал использовать другого клиента. вы можете вставить хотя бы те строки, которые вы используете для выполнения запроса? Вы используете его функцию тайм-аута?

Одним из них может быть:

try:
     resp = requests.post(self._endpoint, json=request_data)

     if resp.status_code != 200:
          logger.critical("[Error]: status code is {}".format(resp.status_code))
          return None

     response = resp.json()
     return {"intent": response["intent"], "intent_ranking": response["intent_ranking"]}
except ConnectionError as exc:
     logger.critical("[Exception] {}".format(str(exc)))
     return None

Спасибо. Я постараюсь создать из него простой.

В любом случае было бы здорово, если бы кто-то мог прислать нам PR, который воспроизводит поведение либо в качестве примера, либо в качестве модульного теста, чтобы мы убедились, что действительно исправляем правильную вещь.

Не уверен, что это может помочь кому-то, но у меня была такая же проблема при запуске докеризованного веб-приложения фляги, и я решил ее, обновив базовый образ моего файла докеров до python:3.6.9-alpine

Dmesg на хосте обнаружил ошибку сегментации lilibpython3.6m.so.1.0:

[626278.653010] gunicorn[19965]: segfault at 70 ip 00007f6423e7faee sp 00007ffc4e9a2a38 error 4 in libpython3.6m.so.1.0[7f6423d8a000+194000]

Мой образ докера был основан на python:3.6-alpine и выполнял apk update который обновлял python до 3.6.8.

Как сказано, изменение базового изображения на python:3.6.9-alpine решило это для меня.

Я столкнулся с той же проблемой, запустив Flask + Docker + Kubernetes. Увеличение пределов ЦП и памяти решило эту проблему для меня.

То же самое случилось и с нами. Проблема была решена увеличением лимитов ресурсов.

Это внезапно случилось со мной на macOS Catalina (не в контейнерах).

Мне помогли:

  1. Установка openssl:
brew install openssl
  1. Запускаем и добавляем это в мой ~/.zshrc :
export DYLD_LIBRARY_PATH=/usr/local/opt/openssl/lib:$DYLD_LIBRARY_PATH

Источник: https://stackoverflow.com/a/58445755/5811984

У меня аналогичная проблема, и буду благодарен, если кто-нибудь сможет мне помочь.
Вот что у меня было;

" root @ ubuntu-s-1vcpu-1gb-nyc1-01 : ~ # sudo systemctl status gunicorn.service ● gunicorn.service - демон gunicorn Загружен: загружен (/etc/systemd/system/gunicorn.service; отключен; предустановка поставщика: enabled) Активен: активен (работает) с понедельника 2020-02-24 07:48:04 UTC; 44мин назад Основной PID: 4846 (gunicorn) Задач: 4 (ограничение: 1151) CGroup: /system.slice/gunicorn.service ├ ─4846 / home / bright / djangoprojectdir / djangoprojectenv / bin / python / home / bright / djangoprojectdir / djangoprojectenv / bin / gunicorn - ├─4866 / home / bright / djangoprojectdir / djangoprojectenc / djangoprojectdir / djangoprojectenctenc / djangoprojectdir / djangoprojectenctenc / binv / djangoprojectenc / binv / djangoprojectenc / binv / djangoprojectenc / binv / djangoprojectenc / binv / djangoprojectenc / djangoprojectdir / home / djangoprojectenc / bin / django / / bin / gunicorn - ├─4868 / home / bright / djangoprojectdir / djangoprojectenv / bin / python / home / bright / djangoprojectdir / djangoprojectenv / bin / gunicorn - └─4869 / home / bright / djangoprojectdir / djangoprojecten / home / bin / / bright / djangoprojectdir / djangoprojectenv / bin / gunicorn - 24 февраля 07:48:04 ubuntu-s-1vcpu-1gb-nyc1-01 systemd [1]: остановлен демон-пулемет. 24 февраля 07:48:04 ubuntu-s-1vcpu -1gb-nyc1-01 systemd [1 ]: Запущен демон-пулеметчик. 24 февраля 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4846] [ИНФОРМАЦИЯ] Запуск Gunicorn 20.0.4 24 февраля 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4846] [ИНФОРМАЦИЯ] Прослушивание: unix: / run / gunicorn .soc 24 февраля, 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4846] [ИНФОРМАЦИЯ] Использование worker: sync Feb 24 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4866] [ИНФОРМАЦИЯ] Загрузка рабочего с pid: 4866 24 февраля 07:48:05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4868] [ИНФОРМАЦИЯ] Загрузочный рабочий с pid: 4868 24 февраля 2007 г. : 48: 05 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: [2020-02-24 07:48:05 +0000] [4869] [ИНФОРМАЦИЯ] Загрузочный рабочий с pid: 4869 24 февраля 08: 03:41 ubuntu-s-1vcpu-1gb-nyc1-01 gunicorn [4846]: - - [24 / фев / 2020: 08: 03: 41 +0000] "GET / HTTP / 1.0" 400 26 "-" "Mozilla /5.0 (Wi-Fi линии 1-20 / 20 (END) «Кто-нибудь, пожалуйста, помогите мне это исправить?

@BrightNana, можете ли вы дать dmesg и посмотреть, есть ли у вас какие-нибудь ошибки?
dmesg | grep gunicorn может помочь отфильтровать другие ошибки

Привет,
У меня такая же ошибка в debian 9, когда я хочу предоставить gunicorn в качестве службы systemd. Если я запускаю его из интерфейса командной строки, Gunicorn работает без ошибок.

Извлечение из dmesg | grep gunicorn :

Отрывок из journalctl :
Mär 12 07:01:06 build-server gunicorn[828]: [2020-03-12 07:01:06 +0100] [1054] [INFO] Booting worker with pid: 1054 Mär 12 07:01:06 build-server gunicorn[828]: [2020-03-12 07:01:06 +0100] [1057] [INFO] Booting worker with pid: 1057 Mär 12 07:01:06 build-server gunicorn[828]: [2020-03-12 07:01:06 +0100] [1060] [INFO] Booting worker with pid: 1060 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1064] [INFO] Booting worker with pid: 1064 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1067] [INFO] Booting worker with pid: 1067 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1070] [INFO] Booting worker with pid: 1070 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1073] [INFO] Booting worker with pid: 1073 Mär 12 07:01:07 build-server gunicorn[828]: [2020-03-12 07:01:07 +0100] [1076] [INFO] Booting worker with pid: 1076 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1079] [INFO] Booting worker with pid: 1079 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1082] [INFO] Booting worker with pid: 1082 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1085] [INFO] Booting worker with pid: 1085 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1088] [INFO] Booting worker with pid: 1088 Mär 12 07:01:08 build-server gunicorn[828]: [2020-03-12 07:01:08 +0100] [1091] [INFO] Booting worker with pid: 1091 Mär 12 07:01:09 build-server gunicorn[828]: [2020-03-12 07:01:09 +0100] [1094] [INFO] Booting worker with pid: 1094
Извлечение из systemctl status :
● api.service - API Server for BuildingChallenge served with Gunicorn Loaded: loaded (/etc/systemd/system/api.service; disabled; vendor preset: enabled) Active: active (running) since Thu 2020-03-12 08:26:01 CET; 22min ago Main PID: 8150 (gunicorn) Tasks: 3 (limit: 4915) Memory: 37.7M (high: 100.0M max: 500.0M) CGroup: /system.slice/api.service ├─ 8150 /opt/api/venv/bin/python /opt/api/venv/bin/gunicorn --bind unix:api.sock wsgi:app ├─28936 /opt/api/venv/bin/python /opt/api/venv/bin/gunicorn --bind unix:api.sock wsgi:app └─28938 /usr/bin/python3 -Es /usr/bin/lsb_release -a Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28909] [INFO] Booting worker with pid: 28909 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28912] [INFO] Booting worker with pid: 28912 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28915] [INFO] Booting worker with pid: 28915 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28918] [INFO] Booting worker with pid: 28918 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28921] [INFO] Booting worker with pid: 28921 Mär 12 08:48:01 build-server gunicorn[8150]: [2020-03-12 08:48:01 +0100] [28924] [INFO] Booting worker with pid: 28924 Mär 12 08:48:02 build-server gunicorn[8150]: [2020-03-12 08:48:02 +0100] [28927] [INFO] Booting worker with pid: 28927 Mär 12 08:48:02 build-server gunicorn[8150]: [2020-03-12 08:48:02 +0100] [28930] [INFO] Booting worker with pid: 28930 Mär 12 08:48:02 build-server gunicorn[8150]: [2020-03-12 08:48:02 +0100] [28933] [INFO] Booting worker with pid: 28933 Mär 12 08:48:02 build-server gunicorn[8150]: [2020-03-12 08:48:02 +0100] [28936] [INFO] Booting worker with pid: 28936

Спасибо за вашу помощь.

Я выставил PR, который мог бы помочь отладить подобные ситуации. Кто-нибудь может посмотреть?
https://github.com/benoitc/gunicorn/pull/2315

У меня была такая же проблема с приложением Flask, работающим внутри Docker. Рабочие бесконечно перезапускались с увеличивающимся идентификатором процесса.
image

Для меня проблема была связана с памятью, когда я увеличил объем памяти, разрешенный для Docker, рабочие рождались эффективно.
image

@tilgovi , я не возражаю, если вы захотите включить мои изменения в свой PR, поскольку вы туда попали первым. Это покроет убитые рабочие с помощью сигналов.

@mildebrandt Я посмотрю, спасибо!

Я также внезапно вижу такое поведение, используя Gunicorn (20.0.4) + Gevent (1.5.0) + Flask внутри контейнера Docker.

[  328.699160] gunicorn[5151]: segfault at 78 ip 00007fc1113c16be sp 00007ffce50452a0 error 4 in _greenlet.cpython-37m-x86_64-linux-gnu.so[7fc11138d000+3e000]

В моем случае, как вы можете видеть, segfault вызван gevent. Что странно, так это то, что этот контейнер работал нормально 5 дней назад, и с тех пор ни одно из изменений кода не изменило никаких версий какой-либо из библиотек, и все они настроены на определенные выпуски. Я удалил flask-mail как зависимость, которая могла немного изменить версии других зависимостей.

Обновление с gevent == 1.5.0 до gevent == 20.9.0 решило проблему для меня.

@ifiddes, ваша проблема, скорее всего, не связана. Вы видите проблему совместимости ABI между старыми версиями gevent с гринлетом самой последней версии. См. Https://github.com/python-greenlet/greenlet/issues/178

Ах, спасибо @jamadden. Этот пост был всем, что я смог найти при поиске бесконечного порождения загружающихся рабочих, но эта проблема и время ее появления соответствовали моей проблеме.

У меня была аналогичная ошибка с новой машиной AWS с сервером Ubuntu 20.04 и с тем же кодом, который работает в производственной среде.

Машина была настроена с использованием Ansible, как и другие производственные машины.

[2020-10-15 15:11:49 +0000] [18068] [DEBUG] Current configuration:
  config: None
  bind: ['127.0.0.1:8000']
  backlog: 2048
  workers: 1
  worker_class: uvicorn.workers.UvicornWorker
  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: /var/www/realistico/app
  daemon: False
  raw_env: []
  pidfile: None
  worker_tmp_dir: None
  user: 1001
  group: 1001
  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: /var/www/realistico/logs/gunicorn/access.log
  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: /var/www/realistico/logs/gunicorn/error.log
  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
  dogstatsd_tags: 
  statsd_prefix: 
  proc_name: None
  default_proc_name: realistico.asgi:application
  pythonpath: None
  paste: None
  on_starting: <function OnStarting.on_starting at 0x7f7ba5fdd550>
  on_reload: <function OnReload.on_reload at 0x7f7ba5fdd670>
  when_ready: <function WhenReady.when_ready at 0x7f7ba5fdd790>
  pre_fork: <function Prefork.pre_fork at 0x7f7ba5fdd8b0>
  post_fork: <function Postfork.post_fork at 0x7f7ba5fdd9d0>
  post_worker_init: <function PostWorkerInit.post_worker_init at 0x7f7ba5fddaf0>
  worker_int: <function WorkerInt.worker_int at 0x7f7ba5fddc10>
  worker_abort: <function WorkerAbort.worker_abort at 0x7f7ba5fddd30>
  pre_exec: <function PreExec.pre_exec at 0x7f7ba5fdde50>
  pre_request: <function PreRequest.pre_request at 0x7f7ba5fddf70>
  post_request: <function PostRequest.post_request at 0x7f7ba5f6e040>
  child_exit: <function ChildExit.child_exit at 0x7f7ba5f6e160>
  worker_exit: <function WorkerExit.worker_exit at 0x7f7ba5f6e280>
  nworkers_changed: <function NumWorkersChanged.nworkers_changed at 0x7f7ba5f6e3a0>
  on_exit: <function OnExit.on_exit at 0x7f7ba5f6e4c0>
  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: None
  raw_paste_global_conf: []
  strip_header_spaces: False
[2020-10-15 15:11:49 +0000] [18068] [INFO] Starting gunicorn 20.0.4
[2020-10-15 15:11:49 +0000] [18068] [DEBUG] Arbiter booted
[2020-10-15 15:11:49 +0000] [18068] [INFO] Listening at: unix:/run/gunicorn.sock (18068)
[2020-10-15 15:11:49 +0000] [18068] [INFO] Using worker: uvicorn.workers.UvicornWorker
[2020-10-15 15:11:49 +0000] [18080] [INFO] Booting worker with pid: 18080
[2020-10-15 15:11:49 +0000] [18068] [DEBUG] 1 workers
[2020-10-15 15:11:51 +0000] [18083] [INFO] Booting worker with pid: 18083
[2020-10-15 15:11:53 +0000] [18086] [INFO] Booting worker with pid: 18086
...
[2020-10-15 15:12:09 +0000] [18120] [INFO] Booting worker with pid: 18120
[2020-10-15 15:12:11 +0000] [18123] [INFO] Booting worker with pid: 18123

После многих неудачных попыток решить эту проблему (и без каких-либо ошибок в журналах) я попытался с этим Hello world и обнаружил эту ошибку:

ModuleNotFoundError: No module named 'httptools'

После установки httptools приложение Hello world работает нормально и, неожиданно, работает и мое приложение.

Я понятия не имею, почему ошибка не была зарегистрирована или почему эта библиотека была установлена ​​на других машинах, но не на новой, но это решило проблему для меня.

Если бы это произошло недавно и отключили узел кубернетов, на котором он был, за счет использования всего ЦП. Благодаря подсказке о dmesg в конце концов я обнаружил ошибку:

[225027.348869] traps: python[44796] general protection ip:7f8bd8f8f8b0 sp:7ffc21a0b370 error:0 in libpython3.7m.so.1.0[7f8bd8dca000+2d9000]

В конце концов, моя проблема заключалась в другом экземпляре https://github.com/python-greenlet/greenlet/issues/178 и была решена путем обновления gunicorn, gevent и greenlet до последней версии.

Поскольку эти типы исключений не создают журналов Python, не могут быть перехвачены, возвращают код выхода 0 и могут повесить машину, когда они возникают, ими довольно сложно управлять.

Я предлагаю, чтобы пулемет обнаруживал быстрое зацикливание такого рода и

  • либо откажитесь, либо ограничьте количество новых рабочих
  • предоставить полезное сообщение, указывающее людям на эту проблему, и https://github.com/python-greenlet/greenlet/issues/178

возможно, max_consecutive_startup_crashes со значением по умолчанию num_workers * 10?

Давайте отследим запрос функции цикла сбоя в # 2504. У нас также есть PR на дополнительный вход в # 2315. Я закрою эту проблему, так как кажется, что все отладили свои проблемы, и теперь у нас есть некоторые запросы функций и улучшения, которые помогут другим в будущем. Спасибо всем!

Была ли эта страница полезной?
0 / 5 - 0 рейтинги