Снижение производительности в mod_rewrite

Снижение производительности в mod_rewrite

Иногда значительное снижение производительности сайта может быть вызвано причинами, на первый взгляд не способными создать какой-либо проблемы. Одной из таких причин являются правила для модуля mod_rewrite в файлах .htaccess веб-сервера Apache. Принципиальное существование такой проблемы легко объясняется тем очевидным фактом, что задавая регулярное выражение, фактически Вы неявно задаете алгоритм поиска данных в строке, и этот алгоритм может оказаться иногда существенно неоптимальным.

С одним из таких примеров мы столкнулись на своем хостинге. Весьма заметное снижение производительности и увеличение нагрузки возникло из-за единственного правила в файле .htaccess:

RewriteRule  ^(([a-z0-9A-Z]+/?)*)(_([a-z0-9A-Z_]+))?$  inner.php?pathstring=$1&urlparams=$3

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

Исследование проблемы

Для иллюстрации снижения производительности на тестовой машине был запущен веб-сервер с файлом .htaccess, в котором было определено правило, приведенное ниже. Это правило — упрощенная версия приведенного выше примера. На нем становится очевидным, что собой представляют вложенные шаблоны без ограничения длины.

RewriteRule   ^(a+)*$   test.html   [L]

Затем с использованием Apache benchmarking tool (программы “ab”) была замерена зависимость скорости отдачи станицы от длины строки с запросом. Команда выглядела следующим образом:

ab -g result.dat -q -n 1000 http://hostname/aaa..aa1 > result.txt

Количество символов “a” в запросе увеличивалось от 1 до 80. График, иллюстрирующий зависимость среднего времени ответа веб-сервера от длины запроса, приведен ниже (обратите внимание, шкала Y логарифмическая).

Видно, что на участке от 1 до 20-22 символов зависимость имеет экспоненциальный характер, после чего время отклика остается примерно постоянным в районе 1.0-1.2 секунд. Дальнейшее исследование показало, что прекращение роста связано с внутренним ограничителем библиотеки libpcre, используемой в Apache: при превышении количества итераций определенного порога поиск по регулярному выражению прекращается с сообщением об ошибке. Значение по-умолчанию для данного порога составляет десять миллионов итераций, и может быть изменено перекомпиляцией библиотеки.

Дополнительные замечания

Нелишне подчеркнуть, что правила, добавленные в .htaccess, проверяются при каждом запросе к веб-серверу, и если для отрисовки Вашей страницы требуется 10-20 запросов, то эта проблема будет проявлять себя 10-20 раз на страницу.

Важно также отметить, что указанная проблема не является проблемой веб-сервера Apache или модуля mod_rewrite. В действительности это проблема алгоритмическая, и может воспроизводиться всюду, где используются регулярные выражения. Кроме того, наличие ограничителя - это характерная особенность библиотеки libpcre. Ее для работы с регулярными выражениями используют многие приложения, в частности названный выше Apache, а также PHP. Однако другие реализации регулярных выражений (в частности, реализация в Python), подобных ограничителей не используют. Это значит, что добавив такую строку в собственный код на Python, Вы получите чисто экспоненциальную зависимость времени выполнения от длины строки, и неограниченные возможности по управлению производительностью вашего сервера злоумышленниками.

Как избежать проблемы

  1. Избегайте вложенных шаблонов с неограниченной длиной.
  2. Если Вы не уверены в безопасности собственного выражения, проведите тест производительности, воспользовавшись, например, утилитой pcretest
  3. Обратитесь к документации, например, к man pcreperform

В качестве дополнительного средства увеличения производительности используйте файлы .htaccess с директивой “RewriteEngine Off”, в каталогах, применение mod_rewrite для файлов внутри которых не предполагается (например, в каталогах с картинками).

С 2003 года
Надежность.
Нам доверяют десятки тысяч компаний и разработчиков
18 лет
Предоставляем услуги профессионального хостинга
35 000
Клиентов доверяют нам размещение своих сайтов
99.99%
Подтвержденный uptime
наших серверов хостинга
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты
Наши клиенты