Поддержка

Мы успешно прошли плановую проверку Роскомнадзора!
05 Май 2012

По результатам проверки нарушений не выявлено.

Наш конкурс: талисманы и приметы Интернет-гуру
17 Апр 2012

Ни одна профессия не обходится без своих суеверий – талисманов и примет. Расскажите нам о своих талисманах и профессиональных приметах и получите настоящий шаманский бубен в качестве приза! Подробности и условия конкурса — в тексте новости.


 

Все новости
RSS RSS

Екатеринбург:

253-55-00

Для регионов России:

8-800-2000-699

Проверить домен:

пример: netangels.ru или 91.201.52.1
Главная > Тех.поддержка > Обзорные статьи > Снижение производительности в 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. Если Вы не уверены в безопасности собственного выражения, проведите тест производительности, воспользовавшись, например, утилитой prcetest
  3. Обратитесь к документации, например, к man pcreperform

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


Теги:  htaccess  mod_rewrite 

Связанные статьи