Опубликован: 16.06.2010 | Доступ: платный | Студентов: 13 / 0 | Оценка: 4.39 / 4.00 | Длительность: 17:32:00
ISBN: 978-5-9963-0253-6
Лекция 3:

Алгоритмизация сжатия текстовых файлов

< Лекция 2 || Лекция 3: 123 || Лекция 4 >
Аннотация: Один из способов, позволяющий уменьшить размер передаваемых данных, — их сжатие. Сжатые данные занимают меньше места, следовательно, быстрее грузятся, и канал и веб-сервер быстрее освобождаются. Производители браузеров позаботились о том, чтобы передаваемые от сервера к клиенту данные можно было запаковать. Все современные браузеры поддерживают один или несколько алгоритмов сжатия данных.

2.1. Методы сжатия, поддерживаемые браузерами


Браузер в каждом запросе к серверу в поле "Accept-Encoding" может указать, какие методы сжатия он поддерживает. Сервер, отвечая на запрос, может выбрать один из указанных браузером методов и, высылая сжатое тело ответа, указать в заголовке (в поле "Content-Encoding"), какой именно метод был выбран.

Вот, к примеру, поле "Accept-Encoding" браузера Opera 10.00:

Accept-Encoding: deflate, gzip, x-gzip, identity, *;q=0

Браузер указал, что поддерживаются два метода сжатия: deflate и gzip. Названия с приставкой "x-" оставлены для совместимости, это историческое название, "gzip" и "x-gzip" (так же как "compress" и "x-compress") эквивалентны. Метод identity ("идентично") означает отсутствие сжатия, то есть данные передаются без изменений. Мы намеренно не рассматриваем остальные значения, подробнее на этом вопросе мы остановимся позже, в части про реализацию сжатия на стороне сервера.

На данный момент браузеры совокупно поддерживают следующие методы сжатия:

  • gzip (x-gzip) —два метода gzip и deflate используют один и тот же алгоритм сжатия — DEFLATE (RFC 1951), использующий комбинацию алгоритма LZ77 и кодирования Хаффмана. В методе gzip (RFC 1952) перед сжатым потоком добавляется десять байт заголовка, а после — восемь байт, состоящие из контрольной суммы (CRC32) и длины несжатых данных;
  • deflate (x-deflate) — представляет собой сжатый алгоритмом DEFLATE поток без заголовка и других метаданных;
  • compress (x-compress) — в данном случае тело ответа такое же, как если бы оно было сжато UNIX-программой compress. Compress использует алгоритм LZC, являющийся реализацией LZW (Lempel— Ziv—Welch), с указателями переменного размера, как в алгоритме LZ78;
  • bzip2 (x-bzip, bzip) — тело ответа совпадает с результатом работы программы bzip2, алгоритм более эффективен, чем compress и семейство DEFLATE, но работает значительно медленнее. В bzip2 применяются преобразование Барроуза-Уилера, MTF-преобразование (move-to-front) и кодирование Хаффмана;
  • sdch (Shared Dictionary Compression Over HTTP) — относительно новый, предложенный компанией Google в сентябре 2008 года метод уменьшения избыточной информации в вебе. Основная идея — не передавать дважды одинаковые куски документа (например, шапку, "подвал" страницы, общие CSS- и JavaScript-файлы). Метод построен на алгоритме VCDIFF (RFC3284), ответ дополнительно может быть сжат любым другим поддерживаемым браузером методом сжатия (например, gzip).

Метод sdch сильно отличается от прочих и имеет смысл только для группы страницы, эффективность же остальных методов проще оценить на примере HTML-страницы, полученной склейкой первых страниц нескольких новостных изданий:

Без сжатия gzip/deflate bzip2 Compress
587828 132023 88263 222091

У архиваторов gzip и bzip2 есть параметр, управляющий эффективностью компрессии, его значение изменяется от единицы до девятки, и чем больше значение, тем эффективнее сжатие и тем больше времени оно занимает. В тесте, проведенном выше, этот параметр для обоих архиваторов был установлен в максимальное значение.

Худший результат типично показывает метод compress, по этой причине многие браузеры отказались от поддержки этого метода. Лучший результат — у bzip2, но этот метод, весьма требовательный к ресурсам, лишь недавно стал появляться в браузерах — на данный момент его поддерживают OmniWeb, w3m, lynx и ранние версии Google Chrome.

Эффективность Gzip bzip2
Исходный размер 189058 Б 189058 Б
1 3,333 мс / 44572 Б 40,282 мс / 32247 Б
2 3,519 мс / 42685 Б 43,716 мс / 29690 Б
3 4,713 мс / 42685 Б 43,765 мс / 29690 Б
4 5,274 мс / 39111 Б 44,213 мс / 29690 Б
5 6,526 мс / 37039 Б 43,704 мс / 29690 Б
6 8,036 мс / 36206 Б 43,814 мс / 29690 Б
7 9,098 мс / 35940 Б 43,934 мс / 29690 Б
8 12,87 мс / 35713 Б 43,725 мс / 29690 Б
9 14,319 мс / 35707 Б 45,129 мс / 29690 Б

На сайте языка программирования PHP, в комментариях к описанию функции gzcompress есть результаты, иллюстрирующие, насколько может зависеть затраченное время и эффективность сжатия архиваторов gzip и bzip2 от параметра, задающего эффективность компрессии, а также приводящие разницу в требованиях к ресурсам этих архиваторов.

Кажущееся странным поведение архиватора bzip2 с параметром, большим единицы (результат архивации не улучшается), объясняется очень просто: параметр от одного до девяти в этом случае задает размер блока — от 100 Кб до 900 Кб.

Что в точности означает этот параметр, для нас маловажно, существенно то, что если выбранный файл (исходный размер — 184,5 Кб) целиком помещается в блок, алгоритм bzip2 не улучшает результат при увеличении размера блока, но сжатие занимает больше времени.

Вывод — если вы настраиваете на сервере сжатие bzip2 в реальном времени, выбирайте размер блока чуть большим, чем средний размер страниц вашего сайта.

У gzip, как видно, зависимость однозначная, оптимальная стратегия в данном случае — установить такой параметр эффективности сжатия, который ваш сервер выдержит, с некоторым запасом.

Существуют также аппаратные решения, позволяющие эффективно сжимать трафик алгоритмом gzip со скоростью вплоть до 10 гигабит в секунду, например, платы расширения фирмы Comtech AHA Corporation.

2.2. Проблемы в браузерах, прокси-серверах и firewall

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

Некоторые браузеры, не испытывая проблем с распаковкой HTML, тем не менее неправильно обрабатывают сжатые файлы CSS и JavaScript.

2.2.1. Opera

Поддерживает методы gzip и defLate.

На данный момент у этого старейшего из используемых браузеров неизвестны какие-либо проблемы, связанные со сжатием.

2.2.2. Internet Explorer

Поддерживает методы gzip и deflate.

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

Проблемными являются версии, начиная с четвертой, заканчивая Internet Explorer 6.0 SP1. Хорошая новость, что в Service Pack 2 этого браузера все проблемы исправлены. К счастью, эта версия отличается полем "Useragent ": его значение содержит подстроку "SV1" ("Security Version 1"), что позволяет отличить эту версию еще на сервере.

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

Доля четвертой и пятой версий в совокупности не превышает 0,5% и продолжает снижаться, с шестой версией несколько сложнее — исследований, определяющих долю IE6SP1, нет, но можно получить оценку сверху: 13%*, если вычесть все IE6, установленные на Windows Vista, где в браузере уже содержится SP2.

2.2.3. Konqueror

Поддерживает gzip и deflate.

Данный браузер не слишком широко известен, но его версии до 3.1 содержат ошибки в реализации метода deflate. Так что если вы не заинтересованы в том, чтобы потерять клиента только из-за того, что он использует не слишком распространенный браузер, лучше метод deflate для проблемных версий отключить.

Также есть сообщения о проблемах со сжатыми методом gzip файлами JavaScript и CSS. Впрочем, доля этого браузера исчезающе мала (менее 0,1%).

2.2.4. Mozilla Firefox

Поддерживает gzip и deflate.

Firefox версий до 3.0x включительно в редких случаях загружает сжатые файлы CSS и JavaScript, не распаковывая их, кроме того, версия 3.0 не правильно загружает файлы этих типов по протоколу HTTPS, если используется Keep-Alive.

Доля проблемных браузеров этого типа — около 26%.

2.2.5. Safari Поддерживает gzip и deflate.

Версии до четвертой включительно неправильно обрабатывают сжатые JavaScript- и CSS-файлы, кроме того, если URL, по которому они скачиваются, заканчивается на .gz, они распознаются как архивы.

2.2.6. Google Chrome

Поддерживает gzip, deflate, bzip2, sdch.

Самый молодой из современных браузеров во второй версии испытывает проблемы с распаковкой CSS и JavaScript: в некоторых подверсиях браузер не пытается распаковать эти файлы, в других загружает их не до конца.

Доля проблемной версии в зарубежном и российском Интернете не превышает 6%.

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

2.2.7. Прокси и firewall

Некоторые типы прокси и firewall имеют ряд проблем, затрудняющих использование сжатия контента.

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

Для этого используется заголовок Vary, он указывает, на каких именно заголовках нужно основываться прокси, чтобы различать, какой контент отдавать браузеру. Для разных наборов значений этих полей попросту хранятся разные копии.

Некоторые довольно распространенные прокси (например, WinGate, Kerio WinRoute) неправильно обрабатывают эту ситуацию, поэтому в том случае, если запрос идет через прокси, контент либо не сжимают вовсе, либо высталяют заголовки, препятствующие кэшированию его на прокси (например, при помощи заголовка Cache-control: private).

Отличить проксированный запрос от непроксированного можно по наличию заголовка Via, которые прокси обязаны выставлять в HTTP-запросах версии 1.1 (RFC 2616). Для запросов HTTP 1.0 такого флага нет, и обычно любой запрос этой версии на всякий случай считается проксируемым.

Вторая проблема подробно обсуждалась в докладе Тони Джентил-кора (он работает в GoogLe) на VeLocity'09 (http://veLocityconference. bLip.tv/fiLe/2293022/), где раскрывается еще одна неприятная подробность: некоторые firewaLL и прокси не пропускают через себя определенную часть заголовков, считая их лишними или опасными. Почему-то в эту часть попал и заголовок Accept-Encoding. В докладе упомянуто, что около 15% ответов остаются несжатыми по этой причине.

Некоторые firewaLL и прокси просто искажают заголовок (например, вместо Accept-Encoding вы получите X-cept-Encoding), другие же просто его удаляют.

Один из способов решить эту проблему, который сразу приходит в голову, — основываться не на Accept-Encoding, а на User-agent, в конце концов мы же знаем, что Internet ExpLorer 8.0 или Firefox 3.5 уж точно поддерживают gzip. Очевидный недостаток — необходимо наличие достаточно большого словаря браузеров, который к тому же нужно пополнять.

В докладе предлагается другой способ: при отсутствии заголовка Accept-Encoding загружать в скрытом фрейме (<iframe>) сжатый некэ-шируемый HTML с JavaScript внутри, который выставляет cookie через JavaScript. Если браузер способен распаковать этот документ, то cookie будет выставлена. В дальнейшем нужно ориентироваться, помимо заголовков, еще и на этот флаг.

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

< Лекция 2 || Лекция 3: 123 || Лекция 4 >
Ольга Артёмова
Ольга Артёмова

Доброго времени суток!

Прошла курс, но почему-то диплом получить не могу, хотя курс значится завершенным, хотя обязательные два модуля пройдены. Как решить эту проблему?

Сертификация: оптимизация и продвижение web-сайтов.

Ярославй Грива
Ярославй Грива
Россия, г. Санкт-Петербург
Ёдгор Латипов
Ёдгор Латипов
Таджикистан, Кургантепа