новости
статьи
.sysadmin

сжатие веб-контента

В настоящее время снижение цен является одной из основных проблем для каждого IT-бюджета. Одним из мест, которому зачастую уделяется пристальное внимание, является цена за полосу пропускания организации. Использование сжатия веб-контента является неплохим способом уменьшить потребности в пропускной способности каналов и, соответственно, снизить затраты на нее. В статье будут рассмотрены некоторые доступные для Apache модули сжатия, в частности, mod_gzip для Apache 1.3.x и 2.0.x и mod_deflate для Apache 2.0.x.

основные принципы сжатия контента

Большинство алгоритмов сжатия при работе с обычными текстовыми файлами позволяет уменьшать их размеры на 70 или больше процентов, в зависимости от содержания файла. Разница между высокими и стандартными уровнями сжатия в данном случае невелика, что является очень важным в деле динамического сжатия веб-контента. Подавляющее большинство методик сжатия используют 6-й уровень сжатия (из 9-и возможных) для сбережения ресурсов процессора. Как правило, разница между 6-м и 9-м уровнем ничтожна, а сбереженные ресурсы системы весьма значительны.

сжатие в HTTP

Для файлов, идентифицируемых как MIME-типы text/.*, сжатие может быть применено непосредственно перед передачей. Это снижает количество передаваемых байт и одновременно увеличивает производительность. Тестирование также показало, что модули компрессии могут эффективно сжимать файлы Microsoft Office, StarOffice/OpenOffice и PostScript.
Существует несколько важных MIME-типов, которые не могут быть сжаты GZIP; это — внешние файлы Java Script, файлы PDF и графика. Проблема с файлами Java Script заключается в основном в ошибках браузерного ПО; так как эти файлы являются текстовыми, то благодаря сжатию перед передачей, производительность должна была бы вырасти. Что же касается PDF-файлов и изображений, то они уже сами по себе являются сжатыми и повторная компрессия только увеличит их размер и вызовет лишние проблемы.
Перед тем, как отсылать сжатый файл клиенту, сервер должен убедится, что тот понимает сжатые форматы данных. Браузеры, которые понимают сжатый контент, отсылают в заголовках запросов нечто вроде этого:
— Accept-encoding: gzip;
— Accept-encoding: gzip, deflate.
Большинство современных браузеров включают некоторую разновидность этих сообщений в каждый отсылаемый запрос. Если сервер увидит заголовок и захочет предоставлять сжатый контент, он должен вставить в заголовок ответа следующее:
Content-encoding: gzip.
Этот заголовок сообщает принимающему информацию браузеру, что ему необходимо осуществить декомпрессию данных и затем обрабатывать как обычно. Также контент может быть передан стороннему приложению основываясь на информации, находящейся в заголовке Content-type.
Выгоды от сжатия файлов можно оценить с помощью пары простых примеров, один для HTML-файла (таблица 1) и второй — для PostScript-файла (таблица 2). Улучшения производительности будут рассмотрены ниже.
Mod_deflate для Apache версий 2.0.44 и более ранних поставляется со степенью сжатия, настроенной для большей скорости, а не для большего сжатия. Эта конфигурация может быть изменена при помощи советов, найденных на www.webcompression.org/mod_deflate-hack.php. Конфигурационная директива включается, начиная с Apache версии 2.0.45.

Таблица 1.

Сжатее Размер Сжатие%

Без сжатия

56,380байт n/a
Apache 1.3.x/mod_gzip 16,333байт 29% от оригинала
Apache 2.0.x/mod_deflate 19,898байт 35% от оригинала
Apache 2.0.x/mod_deflate [2] 16,337байт 29% от оригинала

Таблица 2.

Сжатие Сервер Сжатие%
Без сжатия 63,451байт n/a
Apache 1.3.x/mod_gzip 19,758байт 31% от оригинала
Apache 2.0.x/mod_deflate 23,407байт 37% от оригинала
Apache 2.0.x/mod_deflate [2] 19,942байт 31% от оригинала

настройка mod_gzip

Модуль mod_gzip доступен для Apache 1.3.x и Apache 2.0.x, и может быть откомпилирован как динамический общий объект (DSO, dynamic shared object) или же как статический модуль. Процесс компияции для DSO довольно прост; из директории с исходным кодом необходимо зайдя под root’ом проделать следующие шаги:

make APXS=/path/to/apxs
make install APXS=/path/to/apxs
/path/to/apachectl graceful


Mod_gzip необходимо загрузить в самый конец списка модулей, потому что Apache 1.3.x обрабатывает контент в соответствие с порядком модулей, а так как компрессия является последней стадией обработки, то, соответственно, модуль необходимо поместить последним.

Mod_gzip прописывает себя в файл httpd.conf, но при этом он закомментирован.

Базаовая конфигурация mod_gzip должна включать:

mod_gzip_item_include mime ^text/.*
mod_gzip_item_include mime ^application/postscript$
mod_gzip_item_exclude mime ^application/x-javascript$
mod_gzip_item_exclude mime ^image/.*$
mod_gzip_item_exclude file .(?:exe|t?gz|zip|bz2|sit|rar)$


Это разрешит сжимать файлы PostScript, в то время как PDF-файлы сжиматься не будут. Здесь есть небольшая загвоздка: данные настройки могут вызвать проблемы с Adobe Acrobat Reader. Поэтому следующая строка исправляет эту неприятность, запрещая сжатие PDF:

mod_gzip_item_exclude mime ^application/pdf$.

настройка mod_deflate

Модуль mod_deflate для Apache 2.0.x включен вместе с кодом в поставку сервера, что сильно упрощает его компиляцию:

./configure --enable-modules=all --enable-mods-shared=all --enable-deflate
make
make install


С помощью mod_deflate для Apache 2.0.x сжатие GZIP может быть применено к документам двумя способами: явное исключение файлов по расширению или явное включение файлов по MIME типу. Эти методы определяются в файле httpd.conf. Явное исключение выглядит так:

SetOutputFilter DEFLATE
DeflateFilterNote ratio
SetEnvIfNoCase Request_URI .(?:gif|jpe?g|png)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI .(?:exe|t?gz|zip|bz2|sit|rar)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI .pdf$ no-gzip dont-vary

Явное включение выглядит так:

DeflateFilterNote ratio
AddOutputFilterByType DEFLATE text/*
AddOutputFilterByType DEFLATE application/ms* application/vnd* application/postscript


сжатие динамического контента

Если ваш сайт использует динамический контент, например, XSSI, CGI и тому подобное, то вам не придется делать что-то особенное, чтобы сжать его, так как mod_deflate обрабатывает всю исходящую информацию, перед тем как отправлять ее на канальный уровень. Весь контент Apache, соответствующий MIME-типам или же имеющий расширения, прописанные в конфигурационных директивах, сжимается.
Вывод PHP, одного из самых популярных динамических скриптовых языков для Apache, также может быть сжат одним из следующих способов: с помощью встроенного указателя вывода, ob_gzhandler, с помощью встроенной компрессии ZLIB, или же одним из модулей сжатия Apache.
Настройка встроенной в PHP компрессии является по сути дела компилированием его с опцией --with-zlib с последующим конфигурированием файла php.ini.
Ниже приводятся примерные настройки настройки метода буфферизации исходящего потока данных.

output_buffering = On
output_handler = ob_gzhandler
zlib.output_compression = Off


Метод ZLIB использует:

output_buffering = Off
output_handler =
zlib.output_compression = On


Метод буфера вывода производит немного более лучшее сжатие, но, тем не менее, оба метода работают. Буфер вывода, ob_gzhandler, также может быть добавлен на основе script-by-script если вы не хотите включать сжатие на всем сайте.

Если вы не хотите перенастраивать PHP для включения ZLIB, модули сжатия Apache могут сжимать контент, генерируемый PHP. Например, я настроил мой сервер таким образом, что модули Apache заведуют всем сжатием; все страницы замечательно сжимаются вне зависимости от их происхождения.

кэширование сжатого контента

Может ли кэшироваться сжатый контент? Определенно да! При использовании mod_gzip и mod_deflate, Apache отсылает заголовок Vary, показывая кэшам, что данный объект отличается от других запросов для такого же объекта, основанных на определенном критерии — user-agent, charset и т.д.
Когда сжатый объект принимается кешем, отмечается, что сервер вернул ответ: Vary: Accept-Encoding. Этот ответ показывает, что он был сгенерирован, основываясь на запросе, содержащем заголовок Accept-Encoding: gzip.
Кеширование сжатого контента может привести к тому, что одновременно будут храниться две копии документа: сжатая и распакованная. Такое устройство HTTP 1.1 позволяет клиентам с или без сжатия получить увеличение производительности за счет кешей локальных прокси.

результаты компрессии

Нет смысла делать сравнения при рассмотрении методов ведения логов mod_gzip и mod_deflate. Методика ведения журнала событий mod_gzip весьма надежна, настраиваема и основана на формате log-файлов Apache. Это позволяет сконфигурировать логи mod_gzip для анализа любым образом. Формат, устанавливающийся по умолчанию приведен ниже:

LogFormat "%h %l %u %t "%r" %>s %b mod_gzip: %{mod_gzip_compression_ratio}npct." common_with_mod_gzip_info1
LogFormat "%h %l %u %t "%r" %>s %b mod_gzip: %{mod_gzip_result}n In:%{mod_gzip_input_size}n Out:%{mod_gzip_output_size}n Ratio:%{mod_gzip_compression_ratio}npct." common_with_mod_gzip_info2
LogFormat "%{mod_gzip_compression_ratio}npct." mod_gzip_info1
LogFormat "%{mod_gzip_result}n In:%{mod_gzip_input_size}n Out:%{mod_gzip_output_size}n
Ratio:%{mod_gzip_compression_ratio}npct." mod_gzip_info2

Ведение логов позволяет увидеть размеры файлов до и после сжатия, а также степень сжатия. После настройки log-файлов под ваши специфические нужды, вы сможете добавить их в систему ведения логов, задав параметр CustomLog в файле httpd.conf:

CustomLog logs/gzip.log common_with_mod_gzip_info2
CustomLog logs/gzip.log mod_gzip_info2

Ведение логов в mod_deflate, с другой стороны, ограничено одной конфигурационной директивой DeflateFilterNode, которая добавляется в файл access.log. Будьте осторожны при добавлении этого к вашим рабочим файлам, так как оно может повлиять на некоторые анализаторы логов. Поэтому желательно вести логи в отдельный файл:

DeflateFilterNote ratio
LogFormat '"%r" %b (%{ratio}n) "%{User-agent}i"' deflate
CustomLog logs/deflate_log deflate


улучшение производительности за счет компрессии

Теперь давайте разберемся, насколько все улучшится за счет компрессии? Измерения, произведенные на слабо загруженном сервере, показали, что время загрузки HTML страницы уменьшилось на 1.3-1.6 секунды для медленных соединений.

Рис.1. Время, требуемое для загрузки HTML-страницы с/без сжатия.


Время ответа сервера при запросе сжатой страницы незначительно увеличилось. Измерения показали, что среднее время отклика при запросе несжатой страницы равно 0,23 секунды, в то время как для сжатой оно составило 0,27 секунды. Тем не менее, можно предположить, что большинство администраторов выберут именно сжатие, так как за счет незначительного увеличения времени отклика они получат существенное снижение времени передачи страниц.
Однако веб-страницы — это не только HTML. Как же повлияет улучшенное время загрузки HTML (и CSS) на общую производительность?
На рисунке 2 видно, что общее время загрузки тестовой страницы с компрессией на 1-1,5 секунды лучше времени, когда компрессия не используется.

Рис.2. Время загрузки страниц с изображениями.

Для пущей уверенности в полезности сжатия я провел на веб-сервере еще один тест, определяющий среднюю степень сжатия при запросе большого числа страниц. Вдобавок, я хотел посмотреть, как изменится время отклика сервера при одновременном запросе большого числа сжатых страниц. В тестовой директории было 1952 HTML-файла, результаты получены с использованием cURL в локальной сети (таблицы 3 и 4). Файлы, которые я использовал, являлись документами верхнего уровня из проекта документации Linux (Linux Documentation Project, LDP). Они были записаны на сервер Apache 1.3.27 с установленным mod_gzip. Минимальный размер файла равнялся 80 байтам, а максимальный — 99419 байтам.

Таблица 3.

  Первый байт:
Среднее/
Медиана
Общее время:
 Среднее/
Медиана
Байты:
Среднее/
Медиана
Всего байт
mod_gzip        
Сжатия нет 0.091/0.030 0.280/0.173 6,349/3,750 12,392,318
Сжатие 0.084/0.036 0.128/0.079 2,416/1,543 4,716,160
mod_deflate        
Сжатия нет 0.044/0.028 0.241/0.169 6,349/3,750 12,392,318
Сжатие 0.046/0.031 0.107/0.050 2,418/1,544 4,720,735

Таблица 4.

  mod_gzip mod_deflate
Среднее сжатие 0.433 0.438
Медиана сжатия 0.427 0.427

Как и ожидалось, время загрузки первого байта оказалось для сжатых файлов несколько большим, чем для несжатых. Но разница между ними очень маленькая и измеряется миллисекундами. Скорее всего, любой пользователь, особенно работающий через аналоговый модем, не заметит какого-либо различия.
Однако то, что переданная информация была сжата до 43% от реального размера, заставит сердце любого веб-администратора биться чаще. Степень сжатия варьировалась от «вообще без сжатия» для файлов с размером меньшим 300 байт до 15% от реального размера для руководства по программированию SCSI под Linux. Степень сжатия не растет линейно в зависимости от размера файла, она в большей степени зависит от частоты повторения последовательностей в его содержимом. Руководство по программированию SCSI в этом плане как раз пестрит повторяющимися символами и представляет собой прекрасно подходящий для экстремального сжатия документ. Небольшие файлы не очень хорошо сжимаются по той же причине. Меньшее число байт ведет к уменьшению вероятности их повторения, что в свою очередь, вызывает уменьшение степени сжатия.

Таблица 5 — Среднее сжатие в зависимости от размера файла

  0-999 1,000-
4,999
5,000-
9,999
10,000
19,999
20,000
49,999
50,000-
mod_gzip 0.713 0.440 0.389 0.369 0.350 0.329
mod_deflate 0.777 0.440 0.389 0.369 0.350 0.331



Как видно из таблицы 5, алгоритмы сжатия работают лучше при размере файла, большем 5000 байт. До этого размера степень сжатия намного меньше, кроме случаев, когда в файле находится большое количество повторяющихся символов. Некоторые люди утверждают, что сжатие маленьких файлов только впустую тратит ресурсы процессора, поэтому если вы верите в это, то размер в 5000 байт будет неплохим критерием для определения, нужно сжимать файл или нет. Я же придерживаюсь другой точки зрения. Я сжимаю абсолютно все, что исходит с моих серверов, так как считаю себя HTTP оверклокером и стремлюсь сэкономить каждый лишний байтик, передаваемый по сети.
Mod_deflate не имеет нижней границы размера файлов для сжатия, и поэтому подвергает обработке даже маленькие файлы, сжатие которых не даст абсолютно никакой выгоды. Это приводит к тому, что после обработки файлы, имеющие размер меньше 120 байт, могут становиться больше.

вывод

Легким движением руки вы сможете заставить ваш сервер на базе Apache выдавать большую часть контента в сжатом виде. Вкусить прелести сжатия можно не только на статическом HTML; динамические страницы, генерируемые PHP и другими источниками динамического контента также могут обрабатываться компрессионными модулями Apache. Совместно с другими мерами сжатие может снизить потребности в полосе пропускания.

Стефан Персхала, перевод Дмитрия Герусса.
обсуждение статьи

© сетевые решения
.
.