Статьи

Используйте метрики Heroku для лучшей производительности приложений

3wgIDj3j

Сегодня мы поговорим о продуктах, связанных с производительностью на Rails и Heroku. Я хотел бы представить информационную панель показателей Heroku и узнать, как на этом основании оптимизировать производительность нашего приложения.

Heroku является платформой как услуга (PaaS) для размещения веб-приложений и является одним из самых простых сервисов для быстрого вывода вашего приложения в Интернет. Несмотря на то, что он построен на основе AWS , он имеет множество функций, которые упрощают его и привлекают другие сервисы облачных вычислений. Одной из таких функций является панель метрик, которая дает представление о том, как приложение работает на уровне инфраструктуры.

В этом уроке мы увидим, как использовать это для оптимизации нашего Rails-приложения.

Обратите внимание, что показатели Heroku помогают только на стороне использования ресурсов, таких как процессор, память и ввод-вывод, но это не сильно поможет нам в производительности наших приложений. Существует множество инструментов для мониторинга приложений, таких как New Relic и Skylight . Я определенно рекомендовал бы использовать такие услуги наряду с показателями Heroku.

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

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

Давайте начнем.

Heroku Metrics Обзор

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

Приборная доска

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

Использование памяти

Это дает представление об использовании памяти вашим приложением для типа процесса. Этот показатель обеспечивает общее использование памяти, использование подкачки и квоту памяти. Все эти метрики собраны на уровне динамо. Также есть RSS, который представляет собой общий объем памяти, который есть на всех dyno для выбранного типа процесса.

Dyno Load

Нагрузка Dyno представляет нагрузку, которую несут ваши dyno. Это количество задач ЦП, которые находятся в очереди в ожидании свободного динамо.

События

Это представляет события и ошибки, происходящие в приложении. Такие события, как развертывание, перезапуск и масштабирование, записываются здесь. Кроме того, он фиксирует произошедшие ошибки. Мы рассмотрим некоторые важные ошибки, которые вы часто видите, ниже.

Хотя они регистрируются для всех dyno, есть пара показателей, которые регистрируются только для web

Время отклика

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

пропускная способность

Это дает нам представление о количестве запросов, полученных нашим приложением за минуту. Он показывает количество запросов, которые были успешно обработаны и количество запросов, которые не были обработаны.

ошибки

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

R14 & R15

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

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

R15 — это код ошибки, следующий за R14, если ваше приложение просто не прекратило использовать больше памяти. При возникновении этой ошибки Heroku автоматически перезапустит приложение. Квоту для каждого из планов динамо можно найти здесь .

H10

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

H12 & H13

Эти коды ошибок связаны со временем запроса / ответа. H12 срабатывает каждый раз, когда истекает время запроса, то есть, для возврата ответа требуется более 30 секунд. 30-секундный предел находится на уровне маршрутизатора Heroku.

H13 также является своего рода тайм-аутом запроса, но когда это происходит в приложении. Когда ваш веб-сервер имеет более низкое пороговое значение для времени ожидания запроса, скажем, 10 секунд, а запрос обрабатывается 15 секунд, соединение будет закрыто вашим веб-сервером. Когда это происходит, Heroku запускает H13.

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

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

Образец заявки

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

 rails new heroku-metrics-example -d postgresql
rake db:create && rake db:migrate
rails g scaffold post title body:text
railg g scaffold comment body post:references
rake db:migrate

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

 100.times do |t|
    post = Post.create(title: Faker::Lorem.word, body: Faker::Lorem.paragraphs(3).join(' '))
    puts("Created Post - #{post.id}")
    rand(10..50).times do |c|
        comment = Comment.create(body: Faker::Lorem.paragraph, post: post)
        puts("Created Comment - #{comment.id} for Post #{post.id}")
    end
end

Теперь давайте инициализируем git-репозиторий и развернем его в Heroku:

 git init
git add .
git commit -m "Initial commit"
heroku apps:create
git push heroku master
heroku run rake db:migrate
heroku run rake db:seed

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

Для этого урока я использую хобби-динамик Heroku, который поставляется с 512 МБ ОЗУ. Больше информации о типах динамо здесь

Запрос времени ожидания

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

 siege -t 5M -c 30 https://rocky-coast-29518.herokuapp.com/posts -v

Здесь я генерирую 30 одновременно работающих пользователей в течение 5 минут непрерывно до конечной точки сообщений. После запуска вы можете увидеть влияние, которое оно оказало на приложение, используя метрики Heroku:

Results

Как видите, запросы начали быстро истекать. Почему?

Первой и главной причиной этого является наш веб-сервер. Rails по умолчанию поставляется с WEBrick, который является простым HTTP-сервером для Ruby. Он используется и должен использоваться главным образом для целей развития. WEBrick — это однопоточный веб-сервер без поддержки параллелизма, поэтому одновременно обрабатывается только один запрос. Чтобы это исправить, давайте настроим другой веб-сервер.

Мы собираемся использовать Puma , который является веб-сервером, который рекомендует Heroku.

Добавить веб-сервер довольно просто. Просто добавьте gem "puma"bundle install

После установки создайте файл конфигурации puma в config/puma.rb

 workers Integer(ENV['WORKERS'] || 4)
threads_count = Integer(ENV['THREADS'] || 5)
threads threads_count, threads_count

preload_app!

rackup      DefaultRackup
port        ENV['PORT']     || 3000
environment ENV['RACK_ENV'] || 'development'

on_worker_boot do
  ActiveRecord::Base.establish_connection
end

Я передаю количество работников из переменной среды в метод workers

После настройки создайте файл с именем Procfile

 web: bundle exec puma -C config/puma.rb

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

Gy2YI2p

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

Перегрузка памяти

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

Давайте обновим счет рабочих до 5 и количество потоков до 10 на Heroku. Давайте снова запустим нагрузочное тестирование, на этот раз с большим количеством одновременно работающих пользователей. Ниже приведена обновленная конфигурация нагрузочного теста.

 siege -t 5M -c 200 https://rocky-coast-29518.herokuapp.com/posts -v

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

GoytpSx

Это произошло по нескольким причинам:

  1. Наша настройка рабочих и потоков не совсем корректна. Мы используем 5 рабочих и 10 потоков каждый. Но план БД, используемый в этом примере, имеет максимум 20 соединений. Таким образом, некоторые потоки не получили соединение с БД и на этом этапе произошел сбой.

  2. Поскольку наш счетчик рабочих больше для объема памяти, и поскольку рабочие используют память, мы начали видеть R14.

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

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

Есть также несколько вещей, которые можно исправить на уровне приложений. Например, конечная точка /posts Но мы сосредоточены здесь на оптимизации доступных нам ресурсов. Вы можете узнать больше об оптимизации производительности Rails здесь .

Вывод

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

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

В описанных выше шагах не существует единого стандартного значения, которое можно установить для числа рабочих или потоков, поскольку оно связано с ограничениями приложения, размера dyno и службы (например, БД). Я бы предложил настроить его, пока вы не найдете баланс между использованием ресурсов, пропускной способностью и временем отклика.

Пример приложения, используемого здесь, доступен на github .

Спасибо за прочтение!