Подтвердить что ты не робот

Высокое время реакции Heroku Sporadic

Это очень специфично, но я постараюсь быть кратким:

Мы запускаем приложение Django на Heroku. Три сервера:

  • test (1 web, 1 celery dyno)
  • обучение (1 веб-сайт, 1 сельдерей дино)
  • prod (2 веб-магазина, 1 сельдерей-дино).

Мы используем Gunicorn с gevents и 4 сотрудниками на каждом диновере.

Мы испытываем спорадические высокие времена обслуживания. Вот пример из Logentries:

High Response Time:
heroku router - - at=info 
method=GET 
path="/accounts/login/" 
dyno=web.1 
connect=1ms 
service=6880ms 
status=200 
bytes=3562

Я уже много недель прорабатывал это в Google. Мы не можем воспроизвести по желанию, но испытываем эти оповещения от 0 до 5 раз в день. Известные точки:

  • Происходит во всех трех приложениях (все работает с похожим кодом)
  • Происходит на разных страницах, включая простые страницы, такие как 404 и /admin
  • Происходит случайное время
  • Происходит с различной пропускной способностью. Один из наших экземпляров включает только 3 пользователя в день. Это не связано со спящими динамиками, потому что мы пингом с New Relic, и проблема может произойти в середине сеанса.
  • Невозможно воспроизвести по желанию. Я лично столкнулся с этой проблемой. Щелчок на странице, которая обычно выполняется в 500 мс, привела к задержке в 30 секунд и, в конечном счете, к экрану ошибок приложения с тайм-аутом Heroku 30s
  • Высокое время отклика варьируется от 5000мс до 30000 мс.
  • Новая реликвия не указывает на конкретную проблему. Вот несколько последних транзакций и времен:
    • RegexURLResolver.resolve 4,270ms
    • SessionMiddleware.process_request 2,750ms
    • Render login.html 1,230ms
    • WSGIHandler 1,390ms
    • Вышеприведенные простые вызовы и обычно не занимают такого количества времени.

Что я сузил до:

  • Эта статья о Gunicorn и медленных клиентах
    • Я видел эту проблему с медленными клиентами, но также и в нашем офисе, где у нас есть оптоволоконная связь.
  • Gevent и асинхронные рабочие не играют красиво
    • Мы переключились на сотрудников-бункерных синхронизаторов, и проблема все еще сохраняется.
  • Отключение рабочего времени Gunicorn
    • Возможно, что работники каким-то образом остаются живыми в нулевом состоянии.
  • Недостаточно работников/динамиков
    • Отсутствие индикатора избыточности CPU/памяти/db и New Relic не отображает никаких признаков задержки БД
  • Шумные соседи
    • Среди моих многочисленных писем с Heroku, представитель службы поддержки упомянул, по крайней мере, один из моих длинных запросов был вызван шумным соседом, но не был уверен, что это проблема.
  • Субдомен 301
    • Запросы проходят через штраф, но случайно попадают в приложение.
  • Перезагрузка Dynos
    • Если это так, многие пользователи будут затронуты. Кроме того, я вижу, что наши динамики не перезапускались недавно.
  • Проблема маршрутизации/обслуживания Heroku
    • Возможно, услуга Heroku меньше, чем рекламируется, и это просто недостаток использования их сервиса.

У нас была эта проблема в течение последних нескольких месяцев, но теперь, когда мы масштабируемся, ее нужно исправлять. Любые идеи будут высоко оценены, поскольку я исчерпал почти все ссылки SO или Google.

4b9b3361

Ответ 1

Я поддерживал связь с командой поддержки Heroku за последние 6 месяцев. Это был длительный период сужения проб/ошибок, но мы определили проблему.

В конце концов я заметил, что эти высокие времена отклика соответствовали внезапному обмену памяти, и хотя я платил за стандартный Dyno (который не работал на холостом ходу), эти обмены памяти происходили, когда мое приложение не получало трафика в последнее время. Было также ясно, глядя на диаграммы показателей, что это не утечка памяти, потому что память будет плато. Например:

Внезапная замена памяти

После многих обсуждений со своей командой поддержки мне было предоставлено это объяснение:

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

Мы не изменили, насколько сильно мы упаковываем время автономной работы, поскольку эта проблема стала более очевидной, поэтому наша нынешняя гипотеза заключается в том, что проблема может исходить от клиентов, перемещающихся из версий Ruby до 2.1 до 2.1+. Ruby составляет огромный процент приложений, которые работают на нашей платформе, а Ruby 2.1 внес изменения в GC, который торгует использованием памяти для скорости (по сути, он GC реже, чтобы получить прирост скорости). Это приводит к заметному увеличению использования памяти для любого приложения, перемещающегося из более старых версий Ruby. Таким образом, такое же количество приложений Ruby, которые поддерживали определенный уровень использования памяти, теперь начнет требовать больше использования памяти.

Это явление в сочетании с неправильными приложениями, которые злоупотребляют ресурсами на платформе, попало в точку опроса, которая привела нас к ситуации, которую мы видим сейчас, когда динозавры, которые не должны меняться, являются. У нас есть несколько способов атаки, которые мы изучаем, но пока многие из них все еще немного спекулятивны. Мы точно знаем, что некоторые из этих причин вызваны приложениями, злоупотребляющими ресурсами, и поэтому для перехода к динамическим функциям Performance-M или Performance-L (которые имеют выделенные бэкэнд-серверы) не должно возникать проблемы. Единственное использование памяти на этих динамиках будет вашим приложением. Таким образом, если это произойдет, это будет связано с тем, что ваше приложение вызывает его.

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

Кажется, что нет хорошего решения, кроме A) усилить и подождать или B) переключиться на один из своих выделенных экземпляров

Я знаю толпу, в которой говорится: "Вот почему вы должны использовать AWS", но я нахожу преимущества, которые предлагает Heroku, чтобы перевесить некоторые случайные высокие времена отклика, и их цены стали лучше на протяжении многих лет. Если вы страдаете от одной и той же проблемы, лучшим решением будет ваш выбор. Я обновлю этот ответ, когда услышу что-нибудь еще.

Удачи!

Ответ 2

Не уверен, что это вообще поможет, но сейчас я переживаю одно и то же с помощью приложения Rails прямо сейчас на Heroku - казалось бы, недетерминированных спорадически высоких запросов. Например, HEAD New Relic uptime пингует на мой индекс сайта, который обычно занимает 2-5 мс, занимая 5 секунд, или рендеринг моего входа в сайт, который обычно занимает вторую секцию, занимая 12 секунд. Также иногда получайте случайные тайм-ауты 30 секунд. Здесь, что поддержка Heroku должна была сказать в моем случае (по крайней мере, для некоторых случаев):

Один из предыдущих сегодня выглядит как большой кусок очереди запросов после перезапуска. Если вы хотите этого избежать, вы можете взглянуть на нашу функцию Preboot. Это позволит вам загружать согласованный набор динамиков после развертывания, а затем направлять запросы к ним вместо того, чтобы пинать существующие динамометры и заставлять очередь запросов.

Я должен отметить, что это была одна из стандартных перезагрузок в Хереку, а не развертывание моего или что-то еще. Несмотря на оговорки на странице preboot, я включил его несколько минут назад, поэтому мы посмотрим, имеет ли это значение в моем случае. Надеюсь, что это поможет, так как я тоже вытягиваю свои волосы!