Gunicorn: Мгновенные тайм-ауты работника после длительных запросов

Созданный на 8 авг. 2013  ·  45Комментарии  ·  Источник: benoitc/gunicorn

У нас возникла очень странная проблема, связанная с тайм-аутом запросов при запуске Gunicorn перед нашим приложением Django на Heroku.

По сути, проблема возникает, когда к приложению поступает очень длительный запрос, в результате чего он прерывается таймаутом запроса на уровне платформы Heroku через 30 секунд. Само по себе это не проблема - для таких длительных запросов должно выполняться тайм-аут. Фактическая проблема возникает при следующем запросе. Похоже, есть вероятность, что запрос, выполняющийся _ после_ этого длительного запроса, мгновенно вызовет ошибку Gunicorn в форме:

[CRITICAL] WORKER TIMEOUT (pid:15)

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

Мы запускаем Gunicorn прямо из Django следующим образом:

python app/manage.py run_gunicorn -b 0.0.0.0:$PORT -w 2 -k gevent

Другие соответствующие параметры конфигурации, такие как worker_connections и max_requests, установлены по умолчанию. Однако мы экспериментировали с изменением этих настроек, а также количества рабочих, но проблема, описанная выше, возникает во всех случаях, которые мы пробовали. Наша текущая версия Gunicorn - 0.14.6, с откатом после обновления до 17.5 на случай, если это была источником проблемы. К сожалению, в обеих версиях наблюдается одно и то же поведение.

Нам очень трудно понять основную причину этой проблемы. Из документации Heroku, указанной выше:

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

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

  1. неблокирующий из-за того, что существует несколько рабочих потоков gevent, и
  2. убит Gunicorn до того, как произойдут какие-либо последующие запросы, поскольку тайм-аут запроса по умолчанию для Gunicorn составляет 30 секунд - идентично собственному таймауту запроса Heroku.

Возможно, стоит упомянуть, что длительные запросы подключаются к нашей базе данных PostgreSQL и выполняют несколько сложных запросов. Сбои, похоже, происходят только после тайм-аута длительного соединения благодаря Heroku при взаимодействии с БД. Мы протестировали это на нашем тестовом сервере, создав два отдельных представления, одно из которых выполняет длинные запросы к базе данных до тех пор, пока не будет достигнут тайм-аут Heroku, а другое просто ждет после 30-секундной отметки, чтобы произвести тайм-аут Heroku. Первое представление могло вызывать тайм-ауты рабочего процесса Gunicorn при следующем запросе, тогда как «спящее» представление - нет.

Было бы замечательно, если бы кто-нибудь имел представление о лежащем в основе поведении, вызывающем эту проблему - дайте мне любую дополнительную информацию, которую я могу предоставить для диагностики проблемы. Я надеюсь, что это правильный способ решения такой проблемы и что она не поднималась / не решалась ранее.

( FeaturWorker - Bugs -

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

@Jwpe Отличный отчет об ошибке.

Первое, на что я хотел бы обратить внимание, это то, используете ли вы зеленый драйвер PostgreSQL. Раньше была определенная версия, которую вам нужно было использовать с патчем обезьяны, чтобы это работало правильно. Я не знаю, как обстоят дела сейчас. Но вставленный вами тайм-аут - это тайм-аут рабочего и в одном из асинхронных рабочих процессов, который в основном сводится к «гринлет не дал результата более $ тайм-аута секунд». Учитывая, что вы описываете долго выполняющиеся запросы PostgreSQL, это первое, что я хотел бы исследовать.

@davisp Спасибо за быстрый ответ!

Следуя вашему указателю, я взглянул на адаптер psycopg2, который мы используем для подключения нашего приложения Django к Postgres, и обнаружил этот раздел документации, в котором говорится:

Предупреждение: соединения Psycopg не являются безопасными для зеленых потоков и не могут использоваться одновременно разными зелеными потоками. Попытка выполнить более одной команды одновременно с использованием одного курсора на поток приведет к ошибке (или тупиковой ситуации в версиях до 2.4.2).
Поэтому программистам рекомендуется либо избегать совместного использования соединений между сопрограммами, либо использовать удобную для библиотеки блокировку для синхронизации общих соединений, например, для объединения в пул.

Другими словами, psycopg2 не любит зеленые темы. Основываясь на поведении, с которым мы столкнулись, я мог бы предположить, что это источник ошибки. Предлагаемый способ решения этой проблемы, согласно документации по psycopg, заключается в использовании библиотеки, которая обеспечивает поддержку psycopg для сопрограмм. Рекомендуемая библиотека - psycogreen .

Я попытаюсь воссоздать проблему на нашем тестовом сервере, используя библиотеку psycogreen, и посмотрю, решит ли она проблему. Надеюсь, я смогу сообщить о некоторых результатах относительно скоро.

@Jwpe Похоже на крючок, который я вспомнил.

@benoitc Может быть, нам стоит указать это где-нибудь в документации Gunicorn? Не совсем уверен, где было бы лучшее место.

@davisp может быть в разделе FAQ?

hmppff кстати, он уже существует (http://docs.gunicorn.org/en/latest/faq.html) Так что, возможно, у нас будет ссылка на раздел «Устранение неполадок» оттуда. не уверен, но мы также могли бы перенести в такой раздел любую информацию о virtualenv и других трюках.

Может быть, страница «Предостережения» или «Заметки о зеленых нитях». Не супер прессинг.

Я наблюдал практически то же самое поведение на Heroku, работающем с пулеметом, с рабочими процессами gevent и некоторыми другими, поэтому я переключился на синхронных рабочих, как рекомендовано в этом потоке, и все еще видел в основном ту же серьезную проблему. Я получал 30-секундное отключение Heroku H12, а затем повторял ошибки H12 и [CRITICAL] Worker Timeout до тех пор, пока я не сбрасывал весь динамометр (иногда через час или более позже или до тех пор, пока не было достигнуто максимальное количество запросов). Поэтому я уменьшил тайм-аут Gunicorn до 28 секунд, чтобы он отключился до того, как Heroku отключит его. Такая же (или очень похожая) проблема возникает один или два раза в день и сохраняется до перезапуска главного процесса, только на этот раз она начинается с H13 (соединение закрыто), поскольку Gunicorn отключает его. В это время не наблюдается значительного всплеска трафика.

Вот моя текущая запись в procfile:

web: newrelic-admin run-program gunicorn publisher.wsgi -b 0.0.0.0:$PORT -w 4 --max-requests 1000 --timeout 28 --preload

Деталь серии событий:

Сначала я получаю несколько запросов, которые, кажется, занимают очень много времени (5+ секунд), затем запрос завершается с таймаутом H12 (тайм-аут рабочего отключает его), и еще несколько запросов завершаются, но с исключительно долгим временем (20 секунд). С тех пор это чистая 30-секундная отсечка героку H11, пока я не перезапущу дино.

Мы используем gunicorn (v 18.0) в качестве нашего веб-сервера (который запускает python / django).

Мы запускаем newrelic, который показывает время простоя и безумно увеличенное время ожидания запросов в очереди, но не предлагает никакой другой информации. Не было никаких всплесков пропускной способности или других аномальных условий, которые я вижу в NR. Мы используем papertrail для обработки журналов и рассылки сообщений об ошибках.

Oct 15 15:08:53 nutrislice-stockton heroku/router: at=info method=GET path=/marketingtools/api/slides/?format=json-p&callback=_jqjsp&_1381871332239= host=oldham.nutrislice.com fwd="74.138.24.95" dyno=web.2 connect=15ms service=216ms status=200 bytes=21 Oct 15 15:08:54 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/menutypes/?format=json-p&callback=_jqjsp&_1381871332232= host=oldham.nutrislice.com fwd="74.138.24.95" dyno=web.2 connect=2ms service=90ms status=200 bytes=231 Oct 15 15:08:56 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/schools/?format=json-p&callback=_jqjsp&_1381871323514= host=oldham.nutrislice.com fwd="74.138.24.95" dyno=web.2 connect=3ms service=94ms status=200 bytes=5986 Oct 15 15:09:03 nutrislice-stockton heroku/router: at=info method=HEAD path=/heartbeat/ host=stockton.nutrislice.com fwd="54.247.188.179" dyno=web.2 connect=3ms service=23ms status=200 bytes=0 Oct 15 15:09:13 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/settings/?format=json-p&callback=_jqjsp&_1381871237946= host=pcsb.nutrislice.com fwd="66.87.110.127" dyno=web.2 connect=5ms service=166ms status=200 bytes=468 Oct 15 15:09:20 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/settings/?format=json-p&callback=_jqjsp&_1381871323611= host=oldham.nutrislice.com fwd="74.138.24.95" dyno=web.2 connect=6ms service=183ms status=200 bytes=453 Oct 15 15:09:40 nutrislice-stockton heroku/router: at=info method=GET path=/ host=nps.nutrislice.com fwd="74.190.240.28" dyno=web.2 connect=1ms service=260ms status=200 bytes=35951 Oct 15 15:09:55 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/api/list/school-menu-profile/87/menu-type/43/?format=json-p&callback=jQuery18008709754704032093_1381871379465&_=1381871393589 host=nps.nutrislice.com fwd="74.190.240.28" dyno=web.2 connect=15ms service=129ms status=200 bytes=400 Oct 15 15:09:55 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/api/list/school-menu-profile/306/menu-type/187/?format=json-p&callback=jQuery180013075259909965098_1381873891397&_=1381873896600 host=sdhc.nutrislice.com fwd="72.186.96.121" dyno=web.2 connect=2ms service=33ms status=200 bytes=486 Oct 15 15:10:00 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/186/?smp=257 host=coppellisd.nutrislice.com fwd="76.199.114.157" dyno=web.2 connect=7ms service=103ms status=200 bytes=323 Oct 15 15:10:00 nutrislice-stockton app/web.2: INFO http://stockton.nutrislice.com/heartbeat/ Pinged from IP: 10.190.159.205 -- AGENT: NewRelicPinger/1.0 (269661) Oct 15 15:10:00 nutrislice-stockton heroku/router: at=info method=HEAD path=/heartbeat/ host=stockton.nutrislice.com fwd="50.112.95.211" dyno=web.2 connect=1ms service=10ms status=200 bytes=0 Oct 15 15:10:09 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/239/?smp=341 host=edenpr.nutrislice.com fwd="75.73.177.139" dyno=web.2 connect=8ms service=334ms status=200 bytes=277 Oct 15 15:10:16 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/395/?smp=306 host=sdhc.nutrislice.com fwd="72.186.96.121" dyno=web.2 connect=1ms service=96ms status=200 bytes=245 Oct 15 15:10:20 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/391/?smp=305 host=sdhc.nutrislice.com fwd="173.170.34.126" dyno=web.2 connect=32ms service=5207ms status=200 bytes=290 Oct 15 15:10:22 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/350/?smp=305 host=sdhc.nutrislice.com fwd="173.170.34.126" dyno=web.2 connect=60ms service=7676ms status=200 bytes=1147 Oct 15 15:10:31 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/258/?smp=341 host=edenpr.nutrislice.com fwd="75.73.177.139" dyno=web.2 connect=42ms service=517ms status=200 bytes=26974 Oct 15 15:10:43 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/schools/?format=json-p&callback=_jqjsp&_1381871432885= host=ocps.nutrislice.com fwd="71.47.21.97" dyno=web.2 connect=1490ms service=9883ms status=200 bytes=1565 Oct 15 15:10:52 nutrislice-stockton heroku/router: at=error code=H13 desc="Connection closed without response" method=GET path=/ host=jordandistrict.nutrislice.com fwd="71.199.48.37" dyno=web.2 connect=1959ms service=29230ms status=503 bytes=0 Oct 15 15:10:52 nutrislice-stockton app/web.2: 2013-10-15 21:10:50 [2] [CRITICAL] WORKER TIMEOUT (pid:12) Oct 15 15:10:52 nutrislice-stockton app/web.2: 2013-10-15 21:10:50 [2] [CRITICAL] WORKER TIMEOUT (pid:12) Oct 15 15:10:52 nutrislice-stockton app/web.2: 2013-10-15 21:10:50 [26] [INFO] Booting worker with pid: 26 Oct 15 15:10:52 nutrislice-stockton app/web.2: 2013-10-15 21:10:50,930 (26/MainThread) newrelic.core.agent INFO - New Relic Python Agent (2.0.0.1) Oct 15 15:10:54 nutrislice-stockton heroku/router: at=info method=GET path=/surveys/api/activesurveycount/?format=json-p&callback=_jqjsp&_1381871433429= host=henrico.nutrislice.com fwd="96.248.5.53" dyno=web.2 connect=1181ms service=20074ms status=200 bytes=32 Oct 15 15:10:55 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/schooltypes/?format=json-p&callback=_jqjsp&_1381871433374= host=henrico.nutrislice.com fwd="96.248.5.53" dyno=web.2 connect=1136ms service=20393ms status=200 bytes=142 Oct 15 15:11:01 nutrislice-stockton app/web.2: using heroku production settings Oct 15 15:11:01 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/utils/hashcompat.py:9: DeprecationWarning: django.utils.hashcompat is deprecated; use hashlib instead Oct 15 15:11:01 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:11:01 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/settings/?format=json-p&callback=_jqjsp&_1381871432922= host=ocps.nutrislice.com fwd="71.47.21.97" dyno=web.2 connect=1435ms service=23198ms status=200 bytes=486 Oct 15 15:11:03 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/conf/urls/defaults.py:3: DeprecationWarning: django.conf.urls.defaults is deprecated; use django.conf.urls instead Oct 15 15:11:03 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:11:05 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/schooltypes/?format=json-p&callback=_jqjsp&_1381871443300= host=martinschools.nutrislice.com fwd="99.114.229.202" dyno=web.2 connect=1089ms service=20040ms status=200 bytes=268 Oct 15 15:11:10 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/weeks/school-menu-profile/135/menu-type/63/2013/10/14/?format=json-p&callback=_jqjsp&_1381871439548= host=henrico.nutrislice.com fwd="96.248.5.53" dyno=web.2 connect=1018ms service=30001ms status=503 bytes=0 Oct 15 15:11:15 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/sales/?format=json-p&callback=_jqjsp&_1381871443267= host=martinschools.nutrislice.com fwd="99.114.229.202" dyno=web.2 connect=1096ms service=30001ms status=503 bytes=0 Oct 15 15:11:15 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/schools/?format=json-p&callback=_jqjsp&_1381871443296= host=martinschools.nutrislice.com fwd="99.114.229.202" dyno=web.2 connect=1108ms service=30000ms status=503 bytes=0 Oct 15 15:11:23 nutrislice-stockton heroku/router: at=info method=GET path=/menu/api/weeks/school-menu-profile/48/menu-type/21/2013/10/14/?format=json-p&callback=_jqjsp&_1381871449451= host=martinschools.nutrislice.com fwd="99.114.229.202" dyno=web.2 connect=1114ms service=31756ms status=200 bytes=48771 Oct 15 15:11:26 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/sales/?format=json-p&callback=_jqjsp&_1381871455129= host=pcsb.nutrislice.com fwd="66.87.110.127" dyno=web.2 connect=990ms service=30001ms status=503 bytes=0 Oct 15 15:11:26 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/schools/?format=json-p&callback=_jqjsp&_1381871455291= host=pcsb.nutrislice.com fwd="66.87.110.127" dyno=web.2 connect=1028ms service=30008ms status=503 bytes=0 Oct 15 15:11:31 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menuwidgets/179/?smp=6 host=cusdnutrition.nutrislice.com fwd="68.99.246.16" dyno=web.2 connect=2492ms service=30000ms status=503 bytes=0 Oct 15 15:11:32 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menuwidgets/192/?smp=6 host=cusdnutrition.nutrislice.com fwd="68.99.246.16" dyno=web.2 connect=2713ms service=30003ms status=503 bytes=0 Oct 15 15:11:39 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/ host=hebisd.nutrislice.com fwd="38.107.226.1" dyno=web.2 connect=2115ms service=30001ms status=503 bytes=0 Oct 15 15:11:45 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/weeks/school-menu-profile/44/menu-type/19/2013/10/14/?format=json-p&callback=_jqjsp&_1381871472583= host=pcsb.nutrislice.com fwd="66.87.110.127" dyno=web.2 connect=2168ms service=30000ms status=503 bytes=0 Oct 15 15:11:48 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/marketingtools/api/active-announcements/?format=json-p&callback=_jqjsp&_1381871476287= host=sdhc.nutrislice.com fwd="65.34.72.116" dyno=web.2 connect=1927ms service=30000ms status=503 bytes=0 Oct 15 15:11:48 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/surveys/api/activesurveycount/?format=json-p&callback=_jqjsp&_1381871476543= host=sdhc.nutrislice.com fwd="65.34.72.116" dyno=web.2 connect=2117ms service=30000ms status=503 bytes=0 Oct 15 15:11:48 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/schooltypes/?format=json-p&callback=_jqjsp&_1381871476481= host=sdhc.nutrislice.com fwd="65.34.72.116" dyno=web.2 connect=2111ms service=30009ms status=503 bytes=0 Oct 15 15:11:50 nutrislice-stockton app/web.2: 2013-10-15 15:11:32,597 (26/NR-Activate-Session/nutrislice-stockton) newrelic.core.data_collector INFO - Successfully registered New Relic Python agent where app_name='nutrislice-stockton', pid=26, redirect_host='collector-2.newrelic.com' and agent_run_id=474482914, in 40.26 seconds. Oct 15 15:11:50 nutrislice-stockton app/web.2: INFO Successfully registered New Relic Python agent where app_name='nutrislice-stockton', pid=26, redirect_host='collector-2.newrelic.com' and agent_run_id=474482914, in 40.26 seconds. Oct 15 15:11:52 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/marketingtools/api/active-announcements/?format=json-p&callback=_jqjsp&_1381871480294= host=sdhc.nutrislice.com fwd="65.34.72.116" dyno=web.2 connect=1689ms service=30006ms status=503 bytes=0 Oct 15 15:11:55 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/settings/?format=json-p&callback=_jqjsp&_1381871482566= host=henrico.nutrislice.com fwd="72.84.233.45" dyno=web.2 connect=2067ms service=30004ms status=503 bytes=0 Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:41 [2] [CRITICAL] WORKER TIMEOUT (pid:26) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:41 [2] [CRITICAL] WORKER TIMEOUT (pid:26) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:41 [29] [INFO] Booting worker with pid: 29 Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:41,067 (29/MainThread) newrelic.core.agent INFO - New Relic Python Agent (2.0.0.1) Oct 15 15:11:57 nutrislice-stockton app/web.2: using heroku production settings Oct 15 15:11:57 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/utils/hashcompat.py:9: DeprecationWarning: django.utils.hashcompat is deprecated; use hashlib instead Oct 15 15:11:57 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:44 [2] [CRITICAL] WORKER TIMEOUT (pid:23) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:44 [2] [CRITICAL] WORKER TIMEOUT (pid:23) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:44 [32] [INFO] Booting worker with pid: 32 Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:44,154 (32/MainThread) newrelic.core.agent INFO - New Relic Python Agent (2.0.0.1) Oct 15 15:11:57 nutrislice-stockton app/web.2: using heroku production settings Oct 15 15:11:57 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/utils/hashcompat.py:9: DeprecationWarning: django.utils.hashcompat is deprecated; use hashlib instead Oct 15 15:11:57 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:48 [2] [CRITICAL] WORKER TIMEOUT (pid:14) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:48 [2] [CRITICAL] WORKER TIMEOUT (pid:14) Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:48 [35] [INFO] Booting worker with pid: 35 Oct 15 15:11:57 nutrislice-stockton app/web.2: 2013-10-15 21:11:48,273 (35/MainThread) newrelic.core.agent INFO - New Relic Python Agent (2.0.0.1) Oct 15 15:11:57 nutrislice-stockton app/web.2: using heroku production settings Oct 15 15:11:57 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/utils/hashcompat.py:9: DeprecationWarning: django.utils.hashcompat is deprecated; use hashlib instead Oct 15 15:11:57 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:11:57 nutrislice-stockton heroku/router: at=info method=GET path=/menuwidgets/353/?smp=306 host=sdhc.nutrislice.com fwd="72.186.96.121" dyno=web.2 connect=21ms service=76ms status=200 bytes=255 Oct 15 15:12:00 nutrislice-stockton app/web.2: 2013-10-15 21:11:54 [2] [CRITICAL] WORKER TIMEOUT (pid:13) Oct 15 15:12:00 nutrislice-stockton app/web.2: 2013-10-15 21:11:54 [2] [CRITICAL] WORKER TIMEOUT (pid:13) Oct 15 15:12:00 nutrislice-stockton app/web.2: 2013-10-15 21:11:54 [38] [INFO] Booting worker with pid: 38 Oct 15 15:12:00 nutrislice-stockton app/web.2: 2013-10-15 21:11:54,388 (38/MainThread) newrelic.core.agent INFO - New Relic Python Agent (2.0.0.1) Oct 15 15:12:00 nutrislice-stockton app/web.2: using heroku production settings Oct 15 15:12:01 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/utils/hashcompat.py:9: DeprecationWarning: django.utils.hashcompat is deprecated; use hashlib instead Oct 15 15:12:01 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:12:02 nutrislice-stockton app/web.2: WARNING /app/.heroku/python/lib/python2.7/site-packages/django/conf/urls/defaults.py:3: DeprecationWarning: django.conf.urls.defaults is deprecated; use django.conf.urls instead Oct 15 15:12:02 nutrislice-stockton app/web.2: DeprecationWarning) Oct 15 15:12:03 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menuwidgets/353/?smp=306 host=sdhc.nutrislice.com fwd="108.9.154.78" dyno=web.2 connect=3650ms service=30006ms status=503 bytes=0 Oct 15 15:12:03 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menuwidgets/395/?smp=306 host=sdhc.nutrislice.com fwd="108.9.154.78" dyno=web.2 connect=3581ms service=30006ms status=503 bytes=0 Oct 15 15:12:06 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/settings/?format=json-p&callback=_jqjsp&_1381871492466= host=canyonsdistrict.nutrislice.com fwd="174.52.155.49" dyno=web.2 connect=3582ms service=30001ms status=503 bytes=0 Oct 15 15:12:09 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/mobile/api_version/?deviceType=iphone host=pasco.nutrislice.com fwd="173.65.148.9" dyno=web.2 connect=3837ms service=30004ms status=503 bytes=0 Oct 15 15:12:11 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/mobile/api_version/?deviceType=iphone host=canyonsdistrict.nutrislice.com fwd="174.52.155.49" dyno=web.2 connect=3987ms service=30001ms status=503 bytes=0 Oct 15 15:12:11 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/schools/?format=json-p&callback=_jqjsp&_1381871497105= host=canyonsdistrict.nutrislice.com fwd="174.52.155.49" dyno=web.2 connect=3962ms service=30001ms status=503 bytes=0 Oct 15 15:12:11 nutrislice-stockton heroku/router: at=error code=H12 desc="Request timeout" method=GET path=/menu/api/menutypes/?format=json-p&callback=_jqjsp&_1381871497128= host=canyonsdistrict.nutrislice.com fwd="174.52.155.49" dyno=web.2 connect=4020ms service=30007ms status=503 bytes=0
И эта «смертельная спираль» тайм-аутов H12 и [КРИТИЧЕСКИХ] РАБОЧИХ ТАЙМ-АУТОВ продолжается до тех пор, пока главный процесс не будет перезапущен.

Есть идеи, та же проблема или другая? Есть предложения по исправлению? Я бы подумал, что, поскольку Gunicorn убивает рабочие процессы по истечении времени ожидания и запускает их заново, они смогут начать обрабатывать вещи в обычном режиме, но похоже, что после этого запросы даже не доходят до них. Может быть, это проблема Heroku.

: +1: Тоже наблюдаю эту проблему.

Я тоже вижу эту проблему на Heroku

@sprynmr @richardkeen не могли бы вы рассказать, как вы запускаете Gunicorn, и какие журналы можете? Это очень поможет решить проблему.

@nebstrebor а если не ограничивать количество запросов?

Запускали вот так:
web: newrelic-admin run-program python manage.py run_gunicorn -b "0.0.0.0:$PORT" --log-level=DEBUG -w 3 -k gevent --max-requests 250

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

@sprynmr что если убрать максимальное количество запросов? Также какая версия gevent?

Мы были на 1.0rc2 . Не уверен в максимальном количестве запросов. На самом деле не хочу сейчас снова включать его для нашей производственной среды.

Читая страницу Heroku о тайм-ауте запроса, они предлагают установить тайм-аут приложения well under 30 seconds, such as 10 or 15 . Вы пробовали предложение с использованием параметра тайм-аута в Gunicorn?

В любом случае проблема, возникающая с gevent, вероятно, связана с тем, как обрабатываются соединения. Текущая версия воркера порождает гринлет / принятые соединения без какого-либо реального контроля за этим гринлетом. Что, вероятно, произойдет, так это то, что один из принятых сокетов будет ждать в течение длительного времени, и никакие другие события не будут обрабатываться, что приведет к перезапуску воркера Gunicorn. Но мне нужно проверить ..

Интересно. Нет, мы этого не пробовали.

: +1: Я тоже это вижу в своем приложении. @Jwpe / @sprynmr приходилось ли вам когда-нибудь

Спасибо!

@dencold вы пробовали https://github.com/benoitc/gunicorn/issues/588#issuecomment -29267541

У меня нет аккаунта на heroku, поэтому я не знаю, что он делает. Также у вас есть такие же логи?

Привет @benoitc , большое спасибо за быстрый ответ. Журналы точно такие же, как у @Jwpe и @nebstrebor . Я счастлив вытащить соответствующие биты и добавить их сюда, если это поможет изолировать проблему, просто дайте мне знать.

Я собираюсь воспользоваться вашим советом из вашего предыдущего комментария и настроить тайм-аут Gunicorn так, чтобы он был ниже, чем тайм-аут маршрутизатора heroku, и посмотрю, поможет ли это. Спасибо за предложение.

Было бы полезно выяснить настоящую причину этого каскадного сбоя. Действительно странно видеть, как один рабочий выходит из строя, а затем весь сервер Gunicorn полностью перестает отвечать на запросы. Сообщите мне, чем я могу помочь в диагностике. Я не могу воспроизвести этот тайм-аут локально. Похоже, это происходит только в инфраструктуре героку.

Извините, @dencold, я так и не нашел решения. Это показалось мне очень загадочным багом, и у меня не было времени бороться с ним. Будет любопытно посмотреть, поможет ли вам бит тайм-аута. Доложить.

@dencold , ты тоже

@benoitc да, мы тоже используем новую реликвию.

@dencold , мы так и не решили эту проблему. У нас не было времени на то, чтобы выяснить, что было причиной ошибок, и нам нужно было сосредоточиться на сокращении продолжительности исходных запросов. Однако критический характер ошибки - поскольку она была связана с пользователем - заставило нас переключить серверы WSGI, чтобы избежать проблемы в промежуточный период. Следовательно, мы не проводили никаких дальнейших экспериментов для дальнейшей категоризации проблемы.

@Jwpe вы хоть пробовали предлагаемое решение? К тому же результат получился странным, и я никогда не воспроизводил его с помощью Gunicorn.

У меня было время отключения до 15 секунд, но проблема все еще возникала.

В воскресенье, 26 января 2014 г., Бенуа Шено [email protected]
написал:

@Jwpe https://github.com/Jwpe вы хотя бы пробовали предложенный
решение? К тому же результат получился странным, и я никогда не воспроизводил его с помощью Gunicorn.
сам по себе.

-
Ответьте на это письмо напрямую или просмотрите его на Gi tHubhttps: //github.com/benoitc/gunicorn/issues/588#issuecomment -33316333
.

Бен Робертс
Технический директор
Nutrislice, Inc.
866-524-3444 доб 702
[email protected]

@Jwpe / @nebstrebor большое спасибо за то, что снова

@benoitc мы реализовали предлагаемое решение для тайм-аута на нашем экземпляре heroku. Я буду внимательно следить за этим в ближайшие дни. Отправлю ответ, если увижу ту же проблему, всплывающую после истечения нового тайм-аута.

Еще раз спасибо всем за помощь. Приятно знать, что не только я сталкиваюсь с этой проблемой. Надеюсь, мы сможем разобраться в причине.

@benoitc просто хотел сообщить, что прошло около двух недель с меньшим таймаутом. Мы видели пару тайм-аутов рабочих, но ни один из них не приводил к зависанию всего процесса стрельбы. Кажется, это решает проблему, но я все еще не уверен, почему 30-секундные тайм-ауты вообще вызывали каскадную ошибку.

Просто хотел держать вас в курсе. Еще раз спасибо за помощь!

Такая же [КРИТИЧЕСКАЯ] ошибка РАБОЧЕГО ВРЕМЕНИ при запуске Django с пулеметом в Raspberry PI.

Нет новостей.

У меня такой же [КРИТИЧЕСКИЙ] ТАЙМ-АУТ РАБОТНИКА.
Проблема в том, что после реального тайм-аута рабочего (длинный запрос) пулемет убивает рабочего и пытается создать новый, но новый рабочий не может запуститься в пределах TIMEOUT и не достигает места, где он сообщает родительскому процессу, что он live, поэтому пулемет убивает его снова и снова :(. В нашем случае проблема была связана с Gevent и Sentry (https://github.com/getsentry/raven-python/issues/305). Sentry просто зависает при запуске .
Кстати, было бы полезно иметь отдельный тайм-аут для времени запуска рабочего и некоторые дополнительные журналы внутри рабочего, которые он не может запустить в течение времени «тайм-аута».

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

В некотором смысле в Gunicorn нет «тайм-аута запроса».

да, тайм-аут рабочего отличается от тайм-аута запроса в асинхронном режиме. Но длительные запросы без каких-либо вызовов функций, где может происходить асинхронное «переключение контекста» (например, «сокет - чтение / запись»), являются причинами тайм-аутов рабочих. К тому же может быть тайм-аут при запуске воркера (когда вообще нет запроса). Но в журналах Gunicorn нет возможности различить эти два разных случая, есть только одно сообщение «РАБОЧИЙ ТАЙМ-АУТ».

Должны ли мы добавить настройку тайм-аута запроса? Это позволило бы приложениям с длинными запусками увеличивать тайм-аут рабочего.

Не думаю, из-за
1) Сложно измерить время выполнения запроса, мы не можем использовать разницу во времени в начале и в конце запроса.
2) Насколько я знаю, в gevent невозможно перехватить таймауты «исполнительных единиц» (количество кода, которое выполняется между переключением контекста).

Тогда есть какие-нибудь предложения?

Если эта проблема возникает только из-за допустимого тайм-аута и потенциально каскадного
таймауты из-за нагрузки на сервер, которая не существует при первом запуске, есть ли
здесь что-нибудь делать? Или эту проблему можно решить, и с этим лучше справиться
оперативно на другом уровне инфраструктуры?
30 июля 2014 г. в 13:14 "Mkrtich" [email protected] написал:

Не думаю, из-за
1) Сложно измерить время выполнения запроса, мы не можем использовать разницу во времени на
попрошайничество и в конце запроса.
2) Насколько я знаю, перехват таймаутов «исполнительных блоков» (количество кода
который выполняется между переключением контекста) невозможно в gevent.

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/benoitc/gunicorn/issues/588#issuecomment -50673040.

Предлагается иметь 2 параметра тайм-аута и 2 разных журнала.
1) Один из них - это текущий параметр тайм-аута, который будет работать только во время обработки запроса.
2) Второй - тайм-аут запуска воркера.

Также вижу эту проблему

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

@nebstrebor ну попробовали ли вы предложение уменьшить тайм-аут?

@CrazyPython билет закрыт. Можете ли вы открыть новый тикет, описать возникшую у вас проблему и как мы можем ее воспроизвести? Это определенно поможет понять, та же проблема, что-то еще и т. Д. :)

Да, как отмечалось выше, это не имело значения. Проблема была спорадической
достаточно (никогда не смог воспроизвести) и достаточно катастрофичен, чтобы нам пришлось
сделать этот ход (прошло больше года). Хотя мне очень нравится Gunicorn,
и мы без проблем используем его вне Heroku.

Бен Робертс
Технический директор и соучредитель
Nutrislice, Inc.
[email protected]
сотовый - 801-735-7845

Во вторник, 30 июня 2015 г., в 8:08, Бенуа Шено [email protected]
написал:

@nebstrebor https://github.com/nebstrebor хорошо, вы пробовали
предложение уменьшить таймаут?

@CrazyPython https://github.com/CrazyPython билет закрыт.
Можете ли вы открыть новый тикет, опишите возникшую у вас проблему и как мы можем
воспроизвести? Это определенно поможет понять, та же ли проблема,
что-то еще и ко :)

-
Ответьте на это письмо напрямую или просмотрите его на GitHub
https://github.com/benoitc/gunicorn/issues/588#issuecomment -117199606.

Думаю, мы тоже сталкиваемся с этой проблемой. Оба воркера (--workers 2) зависли на некоторых длительных запросах, в конечном итоге были убиты (--timeout 20), и мы сразу увидели два H13, а затем мы начали получать перезапуски H12 и WORKER TIMEOUT. Это продолжалось в течение следующих 10 минут, рабочие никогда не обрабатывали запрос, пока не истекло время ожидания и они не перезапустились. Итак, мы перезапустили дино, и это устранило его.

Одна интересная вещь, которую я заметил, что я не видел других заметок - мы видим два H13 (соединение закрыто без ответа) в начале проблемы, а затем, когда мы, наконец, выпустили SIGTERM, мы увидели поток H13 - 48 если быть точным, это то же количество тайм-аутов РАБОТНИКА, которое мы видели (за исключением первых двух, для которых мы сразу увидели H13). Я не совсем понимаю, что это значит, но это кажется подозрительным ....

что такое H13 или H12? Это что-то от героку? Как дается порт, на который будет привязан пулемет? Я подозреваю, что прокси-сервер heroku не определяет, что сокет закрыт.

Также какой рабочий вы используете?

Да, это коды ошибок Heroku:
H12 - Тайм-аут запроса - обычно 30 секунд (https://devcenter.heroku.com/articles/error-codes#h12-request-timeout)
H13 - Соединение закрыто без ответа - (https://devcenter.heroku.com/articles/error-codes#h13-connection-closed-without-response)

Изменить: я только что заметил, что Gunicorn будет использовать PORT, если он существует как переменная среды, так что порт настроен.

Мы используем синхронных работников.

И я также забыл упомянуть, что мы запускаем Gunicorn 19.3.0.

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

Привет, я тоже столкнулся с той же проблемой с gunicorn uvicorn на heroku с файлом процесса администратора new-relic:

newrelic-admin run-program gunicorn -w 4 -k uvicorn.workers.UvicornWorker app.main:fastapi_app -b 0.0.0.0:${PORT:-5000} --log-level info --access-logfile=- --logger-class=gunicorn_color.Logger --preload

Это приводит меня к этому журналу, как только система загружается:

2021-03-19T13:18:19.187532+00:00 heroku[web.1]: State changed from starting to up
2021-03-19T13:18:51.964740+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/" host=api-app-clienti-pr-49.herokuapp.com request_id=8742009a-3e56-4f83-a147-97ff84d4e30b fwd="5.89.111.249" dyno=web.1 connect=1ms service=30003ms status=503 bytes=0 protocol=https
2021-03-19T13:19:04.292784+00:00 heroku[router]: at=error code=H12 desc="Request timeout" method=GET path="/api" host=api-app-clienti-pr-49.herokuapp.com request_id=85b6320a-7728-4074-87eb-b0992e7c3f9d fwd="5.89.111.249" dyno=web.1 connect=3ms service=30001ms status=503 bytes=0 protocol=https
Была ли эта страница полезной?
0 / 5 - 0 рейтинги