Hello,
Выставляю на всеобщее обозрение давно обещанные патчи для mod_proxy
к apache 1.3.9. Патчи делались по ходу разработки и поддержки
различных проектов Web-мастерской (http://web.masterskaya.ru),
таких, как http://www.polit.ru, http://www.regions.ru,
http://www.izvestia.ru и пр., полный список можно посмотреть по
первой ссылке ;)
Данные патчи предназначены для mod_proxy, используемого для
кэширования динамического контента - результатов вывода различных
скриптов. Работоспособность проверялась на платформе
FreeBSD 3.4-RC, хотя по идее проблем на других системах быть не
должно, кроме, возможно, Win32.
Ниже - описаловка, а собственно код - следующим письмом.
DISCLAIMER
Как и полагается в таких случаях, автор ни за что ответственности не
несет ;).
Краткое описание и мотивация.
1) mod_proxy корректно обрабатывает клиентский if-modified-since,
следовательно в ряде случаев может отдавать 304 Use local copy.
это вполне нормально, за исключением тех случаев, когда
кэшируемый контент попадает на страницу с использованием SSI. SSI
использует механизм internal subrequest. Internal subrequest
понимает в качестве ответа только 200 OK, все остальное вызывает
маловразумительную надпись [an error occured while processing
this directive].
как было починено: в proxy_cache.c проверка if-modified-since
производится только если запрос не является internal subrequest.
параллельно в mod_rewrite разрешено использовать правило [P] на
сабреквестах (судя по всему, запрещено это было по вышеописанной
причине, но ответа от RSE мне не удалось добиться).
возможные глюки: не замечено.
2) на активно посещаемых сайтах с часто обновляющимся контентов
пользователи часто нажимают Reload. при этом браузер посылает
заголовок pragma: no-cache, при наличии которого mod_proxy берет
данные не из кэша, а с upstream (и обновляет кэш). при большом
траффике это дает большую нежелательную нагрузку на upstream.
как было починено: в mod_proxy введена конфигурационная директива
IgnoreNoCache <filemask>. при совпадении запрашиваемого с
frontend-сервера URI с маской (не regexp, а обычные wildcards) из
заголовков запроса удаляется Pragma: no-cache, в результате чего
при наличии в кэше соответствующего документа он отдается из
кэша, естественно, если не истек срок, указанный в expires.
недостатки: при некорректном expires документ может "залипнуть" в
кэше. в данном случае многое зависит от значения DefaultExpires.
3) при "протухании" активно перегружаемых разными юзерами документов
в кэше на upstream-сервер прокидывается сразу большое количество
запросов, что приводит к волнообразным всплескам нагрузки на механизмы
динамической генерации контента, что может приводить к фатальным
последствиям - типа полной неработоспособности системы в течение
некоторого времени.
как было починено: введена конфигурационная директива
NoConcurrentCacheUpdates (Off|On), которая запрещает прокидывание
запроса на upstream при следующих условиях: данные есть в кэше,
имеют валидную дату expires, expires уже "наступил", запрос к
данному URI уже забирается с upstream хотя бы одним httpd-процессом.
В результате при протухании данных их забирает только один
процесс, не создавая большой конкурентной нагрузки на upstream.
изменения затронули кроме proxy_cache.c еще scoreboard.h и
mod_status.c - пришлось вводить новый код состояния
SERVER_PROXY_READ.
недостатки: сильно content-зависимая фича, которая именно поэтому
сделана отключаемой, по умолчанию - Off. наверняка могут быть
случаи, в которых ее применение нежелательно. YOU WERE WARNED.
4) нередко upstream-сервер хочет знать реальный IP клиента. Конечно,
есть X-Forwarded-For и специальный модуль для его правильной
генерации. мне не хотелось использовать этот заголовок, чтобы не
смешивать функции прикладного кэширования "под задачу" и
собственно прокси.
как починено: добавляется заголовок X-Real-IP.
недостатки: не замечено ;)
5) совсем мелочи - в proxy_cache.c зачем-то для отладки используются
макросы ExplainX, которые все равно не работают. мне было лень
разбираться почему, и я заменил их на вызов ap_log_rerror с
условием LogLevel debug.
Установка.
Патчи складываются в корень исходников апача, после чего
производится patch -c -p1 < filename.diff на все диффы.
TODO
1) неясной остается ситуация, когда одновременно несколькими
клиентами запрашивается URL, которого ЕЩЕ НЕТ в кэше. очевидно, что
все эти запросы будут прокинуты на upstream. теоретически
ситуация маловероятна - вряд ли документ, который раньше не
спрашивал никто, вдруг спросит одновременно много народу.
2) стратегический план - написать на основе mod_proxy модуль с
ограниченной функциональностью, предназначенный только для
кэширования динамического контента.
Best regards,
Ilya mailto:ilya@zhurnal.ru
=============================================================================
= Apache-Talk@lists.lexa.ru mailing list =
Mail "unsubscribe apache-talk" to majordomo@lists.lexa.ru if you want to quit.
= Archive avaliable at http://www.lexa.ru/apache-talk =