Отслеживаем медленные запросы или Почему тормозит Web-сервер

Бывают ситуации, когда Web-сервер тормозит, медленно выдает страницы, а что именно является причиной, непонятно. Первое что приходит в голову — поставить в скриптах контрольные точки, в которых фиксировать время выполнения скриптов. Это может быть достаточно трудной задачей, а при большой нагрузке и вовсе привести к зависанию. Поэтому сначала лучше попробовать встроенные средства Apache и MySQL: mod_status и лог медленных запросов.

Поскольку чаще всего источником проблем бывают запросы к базе данных, то начать следует с включения лога медленных  запросов. Для этого в файл my.cnf (в секцию [mysqld]) прописываем:

[mysqld]
slow_query_log=1
slow_query_log_file=/var/log/mysql-slow.log
long_query_time=15

Перезапускаем MySQL. Теперь все запросы, которые будут выполняться более 15 секунд, будут записываться в файл, указанный в log-slow-queries с указанием времени выполнения и количества просмотренных рядов.

Если таких запросов слишком много, можно попробовать увеличить long-query-time.

Бывают ситуации, когда медленная работа сервера вызвана не SQL-запросами, а связана с медленной работой самих скриптов (например, из-за ошибок логики происходит зацикливание). Типичные признаки: в логе медленных запросов ничего подозрительного не наблюдается, а команда top показывает, что процессор сильно загружен и в памяти висит более десятка процессов httpd.

В этом случае полезно использовать модуль mod_status Web-сервера Apache. Этот модуль позволяет выводить страницу со списком URL обрабатываемых в данный момент запросов, их распределением по рабочим процессам,  загрузкой процессора и некоторыми другими параметрами, которые могут помочь при отладке. Для того, чтобы включить этот модуль, нужно прописать в httpd.conf (или раскомментировать имеющуюся в файле по умолчанию) строку загрузки модуля:

LoadModule status_module modules/mod_status.so

После этого нужно указать, по какому адресу будет выводиться статистика с помощью директивы Location:

<Location /server-status>
  SetHandler server-status

  Order Deny,Allow
  Deny from all
  Allow from 127.0.0.1
</Location>

Здесь /server-status — это URL, по которому будет доступна страница статистики. С точки зрения безопасности такую информацию крайне нежелательно показывать сторонним людям, поэтому следует ограничить доступ либо по IP (как в данном примере), либо паролем (это делается так же, как для обычного каталога с помощью auth_user), если же это по каким-то причинам делать нежелательно, то хотя бы указать вместо /server-status что-то трудноугадываемое.

Прописывать директиву Location можно как в основной конфигурации, так и для любого виртуального хоста. Но при этом важно помнить: на этом хосте не должен использоваться mod_rewrite (а точнее, правила с проверкой на существование каталога или файла), так как в противном случае будет происходить переадресация в соответствии с правилами mod_rewrite. Другой вариант — прописать правило для /server-status, в соответствии с которым переадресации происходить не будет.

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