Заметки об Apache, часть 1: Архивация и клиентское кэширование

Date April 22nd, 2010 Author Vitaly Agapov

Решил, что надо бы оформить и систематизировать всю ту кашу в моей голове, которая касается поддержания веб-сервера, оптимизации, проксирования и всего прочего. Как обычно – полезно для приведения мыслей в порядок и для возможной экономии времени в будущем.
Скорее всего, тут потребуется целый цикл заметок, но начну пока с динамической архивации контента и клиентского кэширования.

Архивация

Практически все браузеры и прочие веб-клиенты вроде wget поддерживают приём заархивированных страниц. Начиная с версии протокола HTTP 1.1 они указывают поддерживаемые типы сжатия в HTTP-заголовке Accept_Encoding. Видя этот заголовок, Веб-сервер может позволить себе сжать контент соответствующим образом: gzip или deflate. При этом он ещё установит заголовок Content-Encoding в HTTP. Само собой, рентабельность архивации на веб-сервере надо рассматривать в каждом случае индивидуально, ибо палка эта о двух концах: уменьшая размер пакетов и издержки на их передачу, мы тем не менее увеличиваем время обработки пакета и затрачиваемые на архивацию ресурсы сервера.
В основном, зависимость здесь выглядит примерно так – при больших размерах страницы, узком канале и запасе процессорной производительности будет явный выигрыш при использовании модулей gzip или deflate. Напротив, при слабом сервере, широком канале и большом количестве передаваемых маленьких файлов (в пределах нескольких Кб) выгоднее будет не сживать файлы.

Для сжатия используются два модуля – mod_gzip и mod_deflate. Первый умеет сжимать только в gzip, но хорошо. Второй – gzip и deflate, но чуть похуже, если верить опубликованным сравнениям. Задо mod_deflate входит в поставку Apache2 и работает из коробки, так что долго раздумывать нечего. Также стоит упомянуть ещё то, что mod_deflate сжимает файлы на лету, а mod_gzip создаёт временный файл на диске для этого, то есть включает в процесс ещё и дисковую подсистему, что какбе не очень хорошо.

В общем, подключаем модули mod_deflate, mod_headers и пишем в конфиге:

# Включаем сжатие
SetOutputFilter DEFLATE

# Выключаем сжатие для проблемных браузеров
BrowserMatch ^Mozilla/4 gzip-only-text/html
BrowserMatch ^Mozilla/4\.0[678] no-gzip
BrowserMatch \bMSIE !no-gzip !gzip-only-text/html

# Страхуемся от того, что не узнаем браузер из-за прокси
Header append Vary User-Agent env=!dont-vary

# Выключаем архивирование изображений
SetEnvIfNoCase Request_URI \.(?:gif|jpe?g|png)$ no-gzip dont-vary

Кэширование

Кэширование – тоже очень полезный элемент. Написано про это много всего, но тем не менее настраивается оно легко. Тут надо только разобраться с политикой кэширования – насколько быстро кэш должен устаревать, а также возможность сделать неустаревающий кэш и изменяемые имена файлов.
В целом, кэширование управлется некоторыми HTTP-заголовками: Cache-Control, Expires, Last-Modified…

Заголовок Expires

Управление временем кэширования в заголовках Expires производится с помощью модуля Apache mod_expires.
Самая простая конструкция в конфигурации может выглядеть следующим образом:

ExpiresActive On
ExpiresDefault "access plus 1 day"
ExpiresByType text/html A0
ExpiresByType image/gif A2592000
ExpiresByType image/jpeg A2592000
ExpiresByType image/png A2592000
ExpiresByType text/javascript A7200
ExpiresByType text/css A7200

Заголовок просто даёт понять браузеру, что после получения файла в течение определенного промежутка времени этот файл можно брать из кэша, не обращаясь к серверу совсем.

Заголовки Last-Modified и If-Modified-Since

Дополнительно к времени кэширования можно указать время последней модификации файла в заголовке Last-Modified. Тогда при истечении времени кэширования, указанного в Expires, браузер запросит файл и укажет в заголовке If-Modified-Since время последнего изменения того файла, который лежит у него в кэше. Если файл на сервере с тех пор не изменялся, то сервер ответит статусом 304 Not Modified и не будет передавать сам файл.

Заголовки ETag и If-None-Match

Этот вариант практически полностью идентичен предыдущему с той разницей, что вместо даты модификации в заголовках передаётся Тэг (хэш, если угодно) файла, составляемый из размера файла и времени модификации файла. В некоторых случах эта система более гибка и сработает даже, если заменить файл другой, более старой версией.
Сервер, отдавая по запросу файл, указывает в заголовке ETag:

ETag: “686897696a7c876b7e”

При следующей необходимости отобразить этот ресурс браузер пошлет запрос GET с указанием заголовка:

If-None-Match: “686897696a7c876b7e”

Если файл с тех пор не изменился, то сервер ответит статусом 304 Not Modified и сэкономит немного пропускной способности.

Управлется эта фича стандартной директивой FileETag. В качестве параметров ей можно передать список компонентов для составления тэга или “none”, если ETag вообще нужно отключить. Поддерживаются компоненты: INode, Mtime, Size, All. По умолчанию считается, что директива устанавливается с такими параметрами:

FileETag INode MTime Size

Использовать все механизмы разом не предмтавляется жизненно важным, так что ЕТаги можно отключить, сэкономив несколько процессорынх тиков на вычислении хэшей:

FileETag none

Tags:
Category: Apache, Web-dev | 1 Comment »

Comments

Один комментарий на “Заметки об Apache, часть 1: Архивация и клиентское кэширование”

  1. agapoff.name | IT блог » Blog Archive » Заметки об Apache, часть 5: Принудительная компрессия контента

    […] […]

Leave a comment

 Comment Form