вівторок, 3 березня 2009 р.

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

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

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


ExtendedStatus On

SetHandler server-status


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

Добавляем к любому сайту на сервере путь /server-status и смотрим, что там показывается. Если видим много запросов к какому либо сайту в состоянии «W», то можно предположить, что проблема с этим сайтом. Но это будет лишь гипотеза, так как узнать точно ситуацию по нагрузке, используя данный отчет, невозможно.
Используем хитрый ход. Установим модуль 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 добавим следующие строчки:


PerlModule Apache2::ShowStatus
PerlInitHandler Apache2::ShowStatus

Проставим линк на этот файл и перезагрузим 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?

Замечательный препроцессор для iptables

Я вполне хорошо знаю и умею пользоваться iptables, но не могу сказать, что написание сложных правил доставляет мне удовольствие, в отличие от того же pf). GUI для iptables меня обычно либо вводят в шок (например, fwbuilder просто вынес мне мозг, предоставив писать правила для iptables, как обычно, только мышкой), либо не дают всех нужных возможностей, которые есть в iptables.

На днях, наткнулся на совершенно замечательный препроцессор для iptables, который позволяет описывать правила на более высоком уровне. Что абсолютно радует, это человекочитаемость полученного конфига. В общем, я влюбился в эту программу. Зовется она ferm, подробно о ней можно почитать на домашней страничке проекта. Проект активно развивается, последняя версия выходила в этом месяце.

Чтобы вы сразу прониклись, красотой этой программы, кидаю свой конфиг /etc/ferm/ferm.conf с моего десктопного компа:

# -*- shell-script -*-
#
# Configuration file for ferm(1).
#

table filter {
chain INPUT {
policy DROP;
# connection tracking
mod state state INVALID DROP;
mod state state (ESTABLISHED RELATED) ACCEPT;
# allow local packages
interface lo ACCEPT;
# respond to ping
proto icmp ACCEPT;
interface eth1 {
mod state state NEW {
# pdns-recursor
proto (tcp udp) dport domain ACCEPT;
proto tcp {
# ssh
dport ssh ACCEPT;
# pulseaudio
dport 4713 ACCEPT;
# mysql
dport 3306 ACCEPT;
# memcached
dport 11211 ACCEPT;
}
}
}
}
chain OUTPUT {
policy ACCEPT;
# connection tracking
#mod state state INVALID DROP;
mod state state (ESTABLISHED RELATED) ACCEPT;
}
chain FORWARD {
policy DROP;
# connection tracking
mod state state INVALID DROP;
mod state state (ESTABLISHED RELATED) ACCEPT;
mod state state NEW {
interface eth1 ACCEPT;
outerface eth1 ACCEPT;
}
}
}
table nat {
chain POSTROUTING {
outerface (ppp0 ppp1) saddr 192.168.0.0/24 MASQUERADE;
}
}
# vim:sw=4 ts=4: