Apache 2.x под наблюдением – 2

Что нового в mod_performance 0.2?

Хочу заострить еще раз внимание, для чего модуль предназначается:

  • модуль предназначен для сбора и накопления статистики по использованию ресурсов(CPU и memory, время выполнения скрипта, а так же I/O процесса) веб-сервером Apache 2.2;
  • модуль позволяет провести анализ собранных данных.

Если кратко описать новшества, то получится примерно такой список:

  • Сохранение собранной модулем информации в БД MySQL.
  • Сохранение собранной модулем информации в отдельный текстовый лог в заданном пользователем формате.
  • Расширено число собираемых данных, т.е теперь единицы собираемой статистики не ограничиваются процентами, но еще сохраняются в секундах и мегабайтах
  • Сохранение собранной модулем информации в БД PostgreSQL.
  • Исправлен ряд ошибок, влияющих на стабильность работы в 0.1-х версии.
  • Добавлена совместимость работы модуля с конфигурациями Apache-itk, а так же Apache+mod_ruid2.
  • Добавлен сбор статистики операций ввода вывода отслеживаемого процесса.
  • Уменьшено влияние модуля на работоспособность сервера, т.е модуль больше не выдает ошибку 503 при невозможности соединится с демоном.

Каковы принципы работы модуля?

Повторюсь еще раз для тех, кто не читал предыдущую статью[2] и добавлю новых сведений.
Модуль позволяет отслеживать за тем, сколько ресурсов потребляет поступивший веб-серверу запрос. Каждый раз сохраняя порцию данных об отработавшем запросе.
Сразу оговорюсь, что данные о запросе сохраняются только после завершения запроса, т.е данные накапливаются для истории и анализа. Тем кому интересно текущая нагрузка сервера — используйте mod_status.
В качестве анализатора использования ресурсов, используется не scoreboard, как в mod_status и расширениях perl, а glibtop.
Модуль позволяет отслеживать как абсолютно все запросы, так и конкретные, отфильтрованные по правилу с помощью регулярных выражений. Точнее будет сказано, что модуль ВСЕГДА обрабатывает только те запросы, которые соответствуют фильтру, содержащему регулярное выражение.
А теперь опишу как именно собирается статистика запроса.
При запуске веб-сервера Apache — запускается демон модуля mod_performance. Запустившийся демон открывает unix-сокет и ожидает соединений. При обработке запроса сервером, происходит проверка запроса на условие: необходимо ли для запроса сохранять статистику или нет. Если проверка прошла успешно, процесс сервера, принявший соединение отправляет демону информацию и PID(TID) процесса/потока, который будет обрабатывать запрос. Демон запускает два потока:1) первый поток, который ожидает завершающей передачи данных от процесса обрабатывающего запрос; 2) поток, который периодически опрашивает использование памяти процессом, обрабатывающим запрос и вычисляет максимальное значение. По окончании работы процесса, обрабатывающего запрос, демон записывает данные в базу данных статистики.

Как собирается статистика об использовании CPU?

Показатель CPU usage вычисляется по следующей схеме. Модуль при поступлении запроса снимает показания jiffies процесса (системы в целом и текущего процесса) и в конце запроса еще раз производится замер и эти данные посылаются демону. На их основании принимается решение об использовании процессора. Т.е. если наблюдая с помощью top вы увидели загрузку: 0%, 10%, 100%, 20%, то не ожидайте, что модуль сохранит 100%, т.к. сохранится именно то количество временни, которое за время существования запроса было выделено именно на этот процесс. «На глазок» для вышеприведенного примера это число будет равно — 32%.

Как собирается статистика об использовании памяти?

А вот показатель памяти собирается по другому принципу. Во время обработки запроса, демон каждые 10 миллисекунд производит замер использования памяти процессом обрабатывающим запрос и в конце сохраняет самое максимальное значение.

Как собирается статистика об использовании операции ввода-вывода?

Этот показатель отслеживается подобно CPU — производится замер прочитанных и записанных данных процесса в начале запроса и в конце запроса. Разница этих величин переводится в килобайты и сохраняется в базе. Т.е. фактически этот показатель отслеживает число записанных/прочитанных байт в течении существования запроса. Сразу скажу, что в качестве анализируемого источника используется показатель: /proc/[pid]/io — read_bytes, write_bytes, cancelled_write_bytes.

Рекомендации по запуску

По умолчанию модуль все свои файлы: сокет, базу данных sqlite, глобальный лог сохраняет в папку /etc/httpd/log. Но как показала практика, не всегда получается использовать эту папку. Зачастую у демона на нее нет прав, т.к. демон работает под пользователем apache (пишу про CentOS, поэтому именно apache).
Сразу рекомендую на машине, где собираетесь использовать модуль создать папку, например — /statistics/apache. Установить ее владельцем пользователя apache и разрешить ему запись и чтение (только аккуратно с режимами itk и mod_ruid, чтоб модуль с измененным пользователем тоже мог писать в сокет этой папки).

PerformanceSocket /statistics/apache/perfsock

Куда сохранять статистику запросов?

Вот он важный вопрос — куда сохранить собираемую статистику. Для упрощения этой головоломки в новой версии модуля встроена поддержка таких БД как: SQLite, MySQL, PostgreSQL, а так же экзотика — сохранение в файл логов. Теперь не нужно подстраиваться под модуль — он подстроится под вас. Для успешной работы модуля(не в режиме «Сохранение в лог») необходимо наличие на машине хотя бы одной из следующих библиотек:

  • libsqlite3.so;
  • libmysqlclient_r.so;
  • libpq.so.

При сборке пакета наличие mysql-devel, sqlite-devel, postgresql-devel не требуется. Эти библиотеки подгрузятся динамически во время работы модуля. Точнее подгрузится нужная для выбранного режима библиотека.

Пример 1. Работа с SQLite. Самый простой вариант, база данных создается автоматически, таблица создается автоматически, нет необходимости в пользователях и прочее. Только одно очень важное замечание для тех кто уже использовал модуль версии 0.1: в старой базе и новой различаются структуры таблиц, поэтому для успешной работы старую базу лучше удалить. Т.к. cам модуль не пересоздает существующую таблицу.

Для работы с SQLite необходимо:

PerformanceDB /statistics/apache/perfdb
PerformanceLogType SQLite

Пример 2. Работа с MySQL. Более сложный вариант.
Создайте базу данных, например, perf и пользователя perf с правами на эту базу:

mysql> create database perf;
mysql> CREATE USER 'perf'@'localhost' IDENTIFIED BY 'perf';
mysql> GRANT ALL PRIVILEGES ON *.* TO 'perf'@'localhost' WITH GRANT OPTION;

таблицу модуль создаст сам. И теперь в настройках модуля:

PerformanceLogType MySQL
PerformanceDbUserName perf
PerformanceDBPassword perf
PerformanceDBName perf

И опять же очень важное замечание для тех кто уже использовал модуль версии 0.2 более ранних версий чем 0.2-8: в старой базе и новой различаются структуры таблиц, поэтому для успешной работы старую базу лучше удалить. Т.к. cам модуль не пересоздает существующую таблицу.

Пример 3. Работа с PostgreSQL. Более сложный вариант.
Так же необходимо создать базу и пользователя для доступа:

postgres=# CREATE USER perf WITH PASSWORD 'perf';
postgres=# CREATE DATABASE perf;
postgres=# GRANT ALL PRIVILEGES ON DATABASE perf to perf;

в файле /var/lib/pgsql/data/pg_hba.conf

local all all trust
host all all 0.0.0.0/0 trust
host all all : : : 1/128 trust

и наконец настройки модуля:

PerformanceLogType Postgres
PerformanceDbUserName perf
PerformanceDBPassword perf
PerformanceDBName perf

Пример 4. Работа с текстовым логом.
В данном режиме не требуется никаких дополнительных библиотек. Достаточно приписать файл, куда будет консолидироваться статистика.

PerformanceLogType Log
PerformanceLog /statistics/apache/perf.log

По умолчанию данные в этот файл попадают в таком формате:

[%DATE%] from %HOST% (%URI%) script %SCRIPT%: cpu %CPU% (%CPUS%), memory %MEM% (%MEMMB%), execution time %EXCTIME%, IO: R — %BYTES_R% W — %BYTES_W%

что разворачивается в:
[2011-06-05 19:28:28] from example.com (/index.php) script /var/www/example.com/index.php: cpu 0.093897 (0.010000), memory 0.558202 (5.597656), execution time 10.298639, IO: R — 104.000000 W — 248.000000
[2011-06-05 19:28:39] from example.com (/index2.php) script /var/www/example.com/index2.php: cpu 0.000000 (0.000000), memory 0.558202 (5.597656), execution time 10.159158, IO: R — 0.000000 W — 0.000000

А сейчас более подробно. Для этого режима можно задать формат выводимой в лог строки. Для этого существуют предопределенные макроимена:

  • %DATE% — преобразуется в дату начала запроса;
  • %CPU% — использование CPU в процентах;
  • %MEM% — использование памяти в процентах;
  • %URI% — URI запроса
  • %HOST% — имя виртуального хоста, к которому адресовался запрос;
  • %SCRIPT% — имя скрипта;
  • %EXCTIME% — длительность выполнения скрипта в секундах;
  • %CPUS% — сколько секунд система потратило именно на этот процесс в секундах;
  • %MEMMB% — использование памяти в мегабайтах;
  • %BYTES_W% — килобайт записано;
  • %BYTES_R% — килобайт прочитано;
  • %% — вывести знак процента.

К примеру:
Hello from %HOST% I use %CPU% %% cpu today %DATE%
развернется в
Hello from example.com I use 0.23 % cpu today 2011-06-05 19:28:28

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

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

Какие отчеты доступны в новой версии модуля по умолчанию?

Как и прежде в версии 0.1 в новом модуле доступны отчеты:

  • Show output without analytics – вывести собранную информацию без анализа, отфильтрованную по хосту, скрипту и URI(графический и текстовый режим);
  • Maximal %CPU – вывести только записи с максимальным значением %CPU(с учетом фильтрации);
  • Maximal memory % — вывести только записи с максимальным значением %memory(с учетом фильтрации);
  • Maximal execution request time – вывести самыйдолго выполняющийся скрипт;
  • Host requests statistics – вывести статистику обращений к хостам с сортировкой по убыванию (в % от общего числа с учетом фильтров);
  • Number of requests per domain — вывести статистику обращений к хостам с сортировкой по убыванию(не в процентах а количество);
  • Average usage per host — вывести среднюю загрузку сервера каждым хостом(сумма % CPU, сумма % MEMORY, сумма выполнения скриптов, средний % CPU за период, средний % использования памяти, среднее время выполнения скриптов);
  • Show current daemon threads — показать список отслеживаемых демоном запросов (отображается только для хендлера performance-status и при включенном параметре PerformanceExtended).

Выводимые поля в отчетах:

  • ID — идентификатор записи;
  • DATE ADD — когда прошел запрос;
  • HOSTNAME — имя виртуального хоста;
  • URI — uri запроса;
  • SCRIPT — выполнявшийся скрипт;
  • CPU(%) — использование CPU в %;
  • MEM(%) — использование памяти в %;
  • TIME EXEC(sec) — время выполнения запроса;
  • CPU TM(sec) — процессорное время в секундах;
  • MEM USE(Mb) — использование памяти в мегабайтах;
  • IO READ(Kb) — прочитано Кбайт процессом;
  • IO WRITE(Kb) — записано Кбайт процессом.

Отчеты доступны в режиме: SQLite, MySQL, Postgres.

Как собрать модуль?

Повторюсь, т.к. по сравнению с предыдущей версией появились изменения (установка под Debian[4]).
Все действия необходимо проводить под пользователем root:
1) установим необходимые пакеты для сборки:

yum install httpd-devel apr-devel libgtop2-devel gd-devel

2) создадим временную паку для исходных кодов:

mkdir ~/my_tmp
cd ~/my_tmp

3) создадим временную паку для исходных кодов:

wget //lexvit.dn.ua/utils/getfile.php?file_name=mod_performance-0.2.tar.gz -O mod_performance-0.2.tar.gz
tar zxvf mod_performance-0.2.tar.gz
cd mod_performance-0.2/

4) собираем модуль:

make

5) на warning не обращаем внимания. Главное, чтоб не было error. Если все собралось нормально, то:

make install

или

cp .libs/mod_performance.so <путь куда копировать>

Инструкция по параметрам модуля доступна по адресу в ссылках[3].

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

С теоретической точки зрения модуль по сути не должен влиять на скорость обработки запроса, т.к. в процессе самого запроса читается только CPU информация, все остальное считывает демон. И основная нагрузка ложится именно на демона. Нагрузка может возрасти на сервер, т.к. демону необходимо обращаться к базе для записи информации. А так же не следует забывать о памяти, которая требуется для работы потоков.
Для исследования практической части этого вопроса было проведено небольшое исследование с помощью утилиты ab (ApacheBench).

1-й тест. Исследовался php скрипт создающий нагрузку на файловую подсистему:

Без модуля mod_performance:

Time taken for tests:   205.952423 seconds
Complete requests:      100
Failed requests:        0
Requests per second:    0.49 [#/sec] (mean)
Time per request:       10297.621 [ms] (mean)
Time per request:       2059.524 [ms] (mean, across all concurrent requests)

С модулем mod_performance:

Time taken for tests:   206.386260 seconds
Complete requests:      100
Failed requests:        0
Requests per second:    0.48 [#/sec] (mean)
Time per request:       10319.313 [ms] (mean)
Time per request:       2063.863 [ms] (mean, across all concurrent requests)

2-й тест. Исследование php скрипта создающего нагрузку на CPU.

Без модуля mod_performance:

Time taken for tests:   60.333852 seconds
Complete requests:      100
Failed requests:        0
Requests per second:    1.66 [#/sec] (mean)
Time per request:       3016.692 [ms] (mean)
Time per request:       603.339 [ms] (mean, across all concurrent requests)

С модулем mod_performance:

Time taken for tests:   60.714260 seconds
Complete requests:      100
Failed requests:        0
Requests per second:    1.65 [#/sec] (mean)
Time per request:       3035.713 [ms] (mean)
Time per request:       607.143 [ms] (mean, across all concurrent requests)

3-й тест. Исследование php скрипта быстро выполняющегося и не создающего нагрузки.

Без модуля mod_performance:

Time taken for tests:   0.075594 seconds
Complete requests:      100
Failed requests:        0
Requests per second:    1322.86 [#/sec] (mean)
Time per request:       3.780 [ms] (mean)
Time per request:       0.756 [ms] (mean, across all concurrent requests)

С модулем mod_performance:

Time taken for tests:   0.109116 seconds
Complete requests:      100
Failed requests:        0
Requests per second:    916.46 [#/sec] (mean)
Time per request:       5.456 [ms] (mean)
Time per request:       1.091 [ms] (mean, across all concurrent requests)

Исследуемая машина: виртуальная, оперативной памяти 1Gb, процессор AMD Phenom(tm) 8650 Triple-Core Processor, ОС CentOS 5.5.

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

Ссылки

  1. Сайт модуля mod_performance — //lexvit.dn.ua/files/
  2. Предыдущая статья о модуле — //habrahabr.ru/blogs/server_side_optimization/119011/
  3. Инструкция по параметрам модуля — //lexvit.dn.ua/articles/?art_id=mod_performance0_2_mht201105267239
  4. Сборка модуля под Debian 6.0 (0.1 версия, спасибо Maxim за статью) —//linuxwork.org.ua/debian/ustanovka-i-nastrojka-modulya-mod_performance-dlya-apache-na-debian-6-0-squeeze/