Uniвсячина

понемножку о Linux и программировании

Мониторинг нагрузки Apache 2

Рассмотрим ситуацию: у вас на сервере хостится несколько сайтов работающих через mod_php под Apache 2.×. Вы обнаруживаете, что сервер начинает тормозить. Запускаете top и видите, что верхние строчки занимает процесс apache2 (или httpd). Ваша задача - узнать какой из сайтов и какими запросами грузит сервер. <!-more—>

Первый шаг — разрешить загрузку модуля mod_status и сконфигурировать его в /etc/apache2/mods-available/status.conf или в /etc/apache2/apache2.conf (я буду писать пути и команды применительно к Debian):

<IfModule mod_status.c>
    ExtendedStatus On
    <Location /server-status>
        SetHandler server-status
    </Location>
</IfModule>

Можно опционально ограничить доступ к URL /server-status по IP-адресу или даже поставить пароль.

Добавляем к любому сайту на сервере путь /server-status и смотрим, что там показывается. Если видим много запросов к какому либо сайту в состоянии “W”, то можно предположить, что проблема с этим сайтом. Но это будет лишь гипотеза, так как узнать точно ситуацию по нагрузке, используя данный отчет, невозможно.

Apache 2 /server-status screenshot

Используем хитрый ход. Установим модуль mod_perl:

apt-get install libapache2-mod-perl2 apache2-prefork-dev

Пакет apache2-prefork-dev нужен для последующей установки перловых модулей. Далее запустим cpan и установим пару модулей:

cpan> install Sys::Proctitle
cpan> install Apache2::ShowStatus

В файл /etc/apache2/mods-available/perl.conf добавим следующие строчки:

<IfModule mod_perl.c>
    PerlModule Apache2::ShowStatus
    PerlInitHandler Apache2::ShowStatus
</IfModule>

Проставим линк на этот файл и перезагрузим Apache:

ln -s /etc/apache2/mods-available/perl.conf /etc/apache2/mods-enabled/
apache2 -t
invoke-rc.d apache2 restart

Смотрим что из этого получилось:

# ps -o user,pid,%cpu,args --sort=-%cpu -u www-data | egrep '^USER|httpd' | grep -v grep
USER       PID %CPU COMMAND
www-data 14039  0.6 httpd: GET /notices_item/????? HTTP/1.0
www-data 14073  0.5 httpd: GET /notice/???????.html HTTP/1.0
www-data 14069  0.5 httpd: GET /r_9/ HTTP/1.0    
www-data 14075  0.5 httpd: GET /notice/???????.html HTTP/1.0

Я заменил часть URL-ов вопросиками из соображений конфиденциальности.

Ну что же, это неплохо, теперь мы видим отсортированные по полю %CPU процессы Apache, а так же видим, какой запрос они выполняют в данный момент. Но мы не видим к какому сайту относятся эти запросы. Придеться немного подпатчить модуль Apache2::ShowStatus в файле /usr/local/share/perl/5.8.8/Apache2/ShowStatus.pm:

--- ShowStatus.pm.orig	2009-01-22 14:19:26.122058102 +0300
+++ ShowStatus.pm	2009-01-22 14:21:01.030847967 +0300
@@ -16,7 +16,7 @@
   my $r=shift;
 
   $r->pnotes( 'ProctitleObject'=>
-	      Sys::Proctitle->new( 'httpd: '.$r->the_request ) );
+             Sys::Proctitle->new( 'httpd: ['.$r->get_server_name().'] '.$r->the_request ) );
 
   return Apache2::Const::DECLINED;
 }

Перезагружаем Apache:

invoke-rc.d apache2 restart

Смотрим, что получилось:

# ps -o user,pid,%cpu,args --sort=-%cpu -u www-data | grep httpd | grep -v grep
www-data 16927  3.3 httpd: [www.????????.ru] GET /img_code.html HTTP/1.0
www-data 16885  3.2 httpd: [76.?????????.ru] GET /notices_item/???????/user_register/ HTTP/1.0
www-data 16921  1.0 httpd: [www.??????.ru] GET /products_item/?????? HTTP/1.0
www-data 16933  0.5 httpd: [www.????????.ru] GET /notice/????????.html HTTP/1.0
www-data 16878  0.5 httpd: [??????????.ru] GET /main_???????? HTTP/1.0
www-data 16930  0.2 httpd: [www.??????????.ru] GET /notice/??????????.html?sd=?????????????????????????????? HTTP/1.0

Ну вот, теперь мы видим и сайт, к которому пришел запрос, и сам запрос.

Кто еще какие способы использует для мониторинга нагрузки на хостинге в окружении Apache2 + mod_php5?

Comments