Золотые сигналы SRE серверов приложений

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

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

PHP

Возможно, PHP уже не так моден, как раньше, но он по-прежнему является основой большинства интернет-сайтов, особенно в электронной коммерции (Magento), Wordpress, Drupal и множестве других крупных систем, основанных на Symfony, Laravel и др. Поэтому игнорировать его мы не можем.

PHP запускается либо как mod_php в Apache, либо, что более распространено, как PHP-FPM, который является отдельным процессом за Apache или Nginx. Оба варианта популярны, хотя mod_php плохо масштабируется.

Для mod_php на базе Apache все просто и плохо. Нет хороших внешних сигналов, поэтому все, что у вас есть - это страница состояния Apache и журналы, о которых говорилось в разделе Золотые сигналы SRE для веб-сервера. Отсутствие метрик у mod_php - еще одна причина использовать PHP-FPM.

Для PHP-FPM нам нужно включить страницу состояния, как мы это делали для Apache и Nginx. Вы можете получить ее в форматах JSON, XML и HTML. Смотрите руководство по Nginx.

Вы также должны включить журналы доступа, ошибок и медленных операций PHP-FPM, которые могут быть полезны для поиска и устранения неисправностей, и позволить странице состояния показывать счетчик событий медленного журнала. Журнал ошибок устанавливается в главном конфигурационном файле PHP-FPM.

Журнал доступа используется редко, но существует, и он нам нужен, поэтому включите его и установите формат, чтобы он включал %d, время, затраченное на обслуживание запросов (это делается в конфигурации POOL, обычно www.conf, а не в основном php-fpm.conf). В этом файле также задается журнал медленной работы. Смотрите эту замечательную страницу.

Наконец, вы должны правильно настроить журналы php. По умолчанию они обычно попадают в журнал ошибок веб-сервера, но затем они смешиваются с 404 и другими веб-ошибками, что затрудняет их анализ или агрегирование. Лучше добавить параметр error_log override (php_admin_value[error_log]) в файл пула PHP-FPM (обычно www.conf).

Для PHP-FPM нашими сигналами являются:

  • Частота (Rate) - К сожалению, нет прямого способа получить этот показатель, кроме как прочитать журналы доступа и объединить их в запросы в секунду.
  • Ошибки (Errors) - Это во многом зависит от того, где PHP регистрирует ошибки, если вообще регистрирует. Журналы ошибок PHP-FPM не слишком полезны, так как они в основном связаны с трассировкой медленных запросов и очень шумные. Поэтому вам следует включить и отслеживать реальные журналы ошибок php, агрегируя их в ошибки в секунду.
  • Задержка (Latency) - Из журнала доступа PHP-FPM мы можем получить время ответа в миллисекундах, как и для Apache/Nginx. Как и в случае с задержками Apache/Nginx, его обычно проще получить от балансировщиков нагрузки, если ваша система мониторинга может это сделать (хотя это будет включать и не-FPM запросы, такие как статические JS/CSS файлы). Если вы не можете получить журналы, вы также можете отслеживать "Slow Requests", чтобы получить количество медленных ответов, которые можно перевести в Slow Requests/sec.
  • Насыщение (Saturation) - отслеживайте "Listen Queue", так как она будет ненулевой, когда больше нет доступных процессов FPM и система FPM насыщена. Обратите внимание, что это может быть связано с CPU, RAM/Swapping, медленным DB, медленным внешним сервисом и т.д. Вы также можете отслеживать "Max Children Reached", который покажет вам, сколько раз вы достигали насыщения по FPM, хотя это не может быть легко преобразовано в скорость (так как вы можете быть насыщены весь день). Но любое изменение этого счетчика во время выборки указывает на насыщение в период выборки.
  • Утилизация (Utilization) - Мы хотели бы отслеживать используемые процессы FPM ("Active Processes") по сравнению с настроенным максимумом, хотя последний трудно получить (разбор конфигурации), и вам, возможно, придется его жестко закодировать.

Java

На Java работает множество более тяжелых веб-сайтов, большая электронная коммерция и сайты со сложной логикой, часто для предприятий. Она работает на различных серверах и в различных средах, но в основном в Tomcat, поэтому здесь мы сосредоточимся на нем. Другие Java-контейнеры должны иметь данные, аналогичные Tomcat, либо через JMX, либо через свои журналы.

Как и все серверы приложений, золотые сигналы лучше отслеживать немного выше по течению на веб-сервере, тем более что часто перед каждым экземпляром Tomcat на одном хосте стоит выделенный сервер Nginx, хотя это становится все менее распространенным. Балансировщики нагрузки непосредственно перед Tomcat (или перед его фронтальным Nginx) также могут предоставить метрики скорости и задержки.

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

JMX предоставляет данные, поэтому мы должны включить его на уровне JVM и перезапустить Tomcat. Когда вы включите JMX, убедитесь, что он доступен только для чтения и включает защиту, ограничивающую доступ к локальной машине, с пользователем, доступным только для чтения. Смотрите хорошее руководство, Docs и хороший PDF по мониторингу.

В последних версиях вы также можете получать данные JMX через Tomcat Manager и HTTP, хотя не забудьте активировать надлежащую безопасность в Manager & interface.

  • Частота (Rate) - Через JMX вы можете получить requestCount GlobalRequestProcessor и сделать дельта-обработку, чтобы получить Requests/Second. Это подсчитывает все запросы, включая HTTP, но мы надеемся, что HTTP является основной частью этих запросов, и, похоже, вы можете указать имя процессора в качестве фильтра, которое должно быть именем вашего настроенного HTTP процессора.
  • Ошибки (Errors) - Через JMX вы можете получить счетчик ошибок GlobalRequestProcessor и выполнить дельта-обработку, чтобы получить количество ошибок в секунду. Включает не-HTTP вещи, если вы не можете отфильтровать их по процессору.
  • Задержка (Latency) - Через JMX вы можете получить время обработки GlobalRequestProcessor's processingTime, но это общее время с момента перезапуска, которое при делении на requestCount даст вам среднее долгосрочное время отклика, но это не очень полезно. В идеале ваша система мониторинга или скрипты могут сохранять оба эти значения при каждой выборке, затем получать разницу и делить их - это не идеально, но это все, что у нас есть.
  • Насыщение (Saturation) - Если текущее значение ThreadPool's currentThreadsBusy = maxThreads, то вы будете стоять в очереди и, следовательно, будет насыщено, поэтому необходимо следить за этими двумя значениями.
  • Утилизация (Utilization) - Используйте JMX для получения (currentThreadsBusy / maxThreads), чтобы узнать, какой процент потоков используется.

Python

Python становится все более популярным для веб-приложений и API-приложений и запускается под различными серверами приложений, начиная с популярного фреймворка Django.

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

Например, такой модуль, как Django / Gunicorn's Statsd, может быть использован для выдачи полезных метрик, которые вы можете собирать, если используете statsd - несколько сервисов, таких как DataDog, могут сделать это за вас. Но вам все равно придется кодировать метрики самостоятельно.

Как и в случае с Node.js, могут существовать библиотеки или фреймворки, которые могут предоставлять эти метрики на основе API, протоколирования или на другой основе. Например, в Django есть модуль Prometheus.
Если вы не используете ни один из этих способов, вам следует найти пути внедрения "золотых сигналов" в ваш код, например:

  • Частота (Rate) - Это сложно реализовать в коде, так как большинство вещей работают на основе каждого запроса. Самый простой способ - установить глобальный счетчик запросов и выдавать его напрямую, хотя это означает использование общей памяти и глобальных блокировок.
  • Ошибки (Errors) - Аналогично получению тарифа, возможно, с использованием глобального счетчика.
  • Задержка (Latency) - Самый простой способ, так как вы можете определить время начала и окончания запроса и выдать метрику длительности.
  • Насыщение (Saturation) - Трудно получить в коде, если только нет данных от диспетчера о доступных работниках и очередях.
  • Утилизация (Utilization) - то же самое, что и насыщенность.
    Если вы не можете сделать ничего из перечисленного, лучше всего получать сигналы от вышестоящего веб-сервера или балансировщика нагрузки.

Node.js

Как и в случае с серверами приложений Python, в Node.js все кажется пользовательским или встроенным в код, поэтому нет стандартного способа мониторинга, чтобы получить сигналы. Многие сервисы мониторинга, такие как DataDog, имеют пользовательские интеграции или поддержку, и существует множество дополнительных модулей для экспорта метрик различными способами.

Существуют некоторые инструменты с открытым исходным кодом / коммерчески открытые инструменты, такие как KeyMetrics и AppMetrics, которые предоставляют API для получения многих из этих данных.

Чтобы внести изменения в код или добавить свои собственные метрики Golden Signal, смотрите краткое описание в разделе Python, выше.

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

Golang

Go запускает свой собственный HTTP-сервер и, как правило, его можно проинструктировать, добавив испускаемые метрики для тех вещей, которые вы хотите видеть, например Latency и Request Rate. Некоторые ставят Nginx (который можно мониторить) перед Go, другие используют Caddy, который может предоставлять Latency через поле {latency_ms}, аналогично Apache/Nginx, но не имеет больших данных о состоянии или скорости (хотя есть плагин Prometheus, который имеет некоторые из них).

Чтобы внести изменения в код или добавить свои собственные метрики Golden Signal, смотрите краткое описание в разделе Python, выше.

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

Ruby

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

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

Для Ruby, работающего под Passenger, вы можете запросить страницу passenger-status, чтобы получить ключевые метрики.

Для Passenger или Apache mod_rails наши сигналы следующие:

  • Частота (Rate) - Получите количество "Обработанных" для группы приложений и выполните дельта-обработку для получения запросов в секунду.
  • Ошибки (Errors) - нет очевидного способа получить это, если только в журналах, но у Passenger нет отдельного журнала ошибок (только очень смешанный журнал, часто общий с веб-сервером, хотя вы можете установить уровень журнала только для ошибок).
  • Задержка (Latency) - этот показатель можно получить из журналов доступа Apache/Nginx. См. раздел "Веб-сервер".
  • Насыщение (Saturation) - показатель "Запросы в очереди" для группы приложений подскажет вам, насколько насыщен сервер. Не используйте "Запросы в очереди верхнего уровня", поскольку, согласно документации, он всегда должен быть равен нулю.
  • Утилизация (Utilization) - Нет очевидного способа получить это значение. Мы можем получить общее количество процессов, но не совсем понятно, как определить, сколько из них заняты. Как и в случае с mod_PHP или PHP-FPM, важно следить за использованием памяти, так как ее можно легко исчерпать.

COBOL & FORTAN

Шучу