Прямой ответ
Сжатие HTTP-ответа согласуется заголовками: клиент указывает поддерживаемые методы в Accept-Encoding, сервер отвечает методом из перечня и указывает его в Content-Encoding.
gzip on;
gzip_types text/plain text/css application/json application/javascript
application/xml text/xml;
gzip_min_length 1024;
gzip_comp_level 5;
gzip_vary on;
| Параметр | Значение |
|---|---|
gzip_types |
Типы содержимого, к которым применяется сжатие |
gzip_min_length |
Порог размера, ниже которого сжатие не выполняется |
gzip_comp_level |
Уровень сжатия |
gzip_vary on |
Заголовок Vary: Accept-Encoding для корректного кэширования |
Сжатие применяется к текстовым типам содержимого, поскольку они содержат избыточность. Изображения и видео уже сжаты, поэтому повторное сжатие расходует время без уменьшения объёма; о пригодности данных — в статье про алгоритмы сжатия.
Порог размера, кэширование и предварительное сжатие
Три параметра определяют, когда сжатие выгодно и как оно взаимодействует с кэшем.
Порог размера. Заголовок сжатого ответа занимает фиксированный объём, поэтому на малых ответах сжатие может не сократить объём передачи. Порог задаётся явно.
Кэширование. Ответ зависит от заголовка Accept-Encoding, поэтому кэш должен различать варианты. Заголовок Vary: Accept-Encoding указывает кэшу учитывать согласование метода. О заголовках кэширования — в статье про HTTP-кэширование.
Предварительное сжатие. Статические файлы сжимаются один раз при сборке, а сервер отдаёт готовый сжатый файл, поэтому время на сжатие не расходуется при каждом запросе.
Практическое следствие: динамические ответы сжимаются на лету, статические — предварительно.
# Отдача заранее сжатого файла, если клиент поддерживает сжатие
gzip_static on;
Отдельный аспект — уровень сжатия для динамических ответов. Высокий уровень увеличивает время обработки запроса, поэтому выбирается по соотношению коэффициента и задержки. О соотношении параметров — в статье про выбор алгоритма.
О размещении сжатия в цепочке прокси — в статье про reverse proxy: сжатие выполняется в одном узле, поскольку повторное сжатие уже сжатого ответа неэффективно.
Сжатие применяется после формирования ответа, поэтому объём передаваемых данных сокращается, но время обработки включает сжатие.
Взаимодействие с прокси и поддержка клиентов
Сжатие в цепочке прокси требует согласования, чтобы ответ не сжимался дважды и клиент получал поддерживаемый вариант.
Один узел сжатия. Сжатие выполняется в одном узле цепочки, поскольку повторное сжатие уже сжатого ответа не уменьшает объём, но расходует процессорное время.
Заголовок согласования. Прокси передаёт заголовок поддержки методов клиентом, поэтому конечный узел выбирает метод из перечня, который клиент действительно поддерживает.
Проверка фактического результата. Ответ проверяется по заголовку метода сжатия и фактическому объёму, поскольку конфигурация может не применяться к определённому типу содержимого.
Практическое следствие: включение сжатия в нескольких узлах цепочки не даёт дополнительного выигрыша, но увеличивает расход процессорного времени.
Отдельный аспект — поддержка методов клиентом. Клиент, не поддерживающий сжатие, получает ответ без сжатия, поэтому доля сжатых ответов зависит от состава клиентов.
Практика: настройка сжатия HTTP-ответов
1. Ограничьте перечень типов содержимого. Сжатие применяется к текстовым типам, поскольку бинарные уже сжаты.
2. Задайте порог размера. На малых ответах заголовок занимает заметную долю, поэтому сжатие может не сократить объём.
3. Включите Vary: Accept-Encoding. Кэш должен различать варианты ответа по методу сжатия.
4. Сжимайте статику предварительно. Готовый сжатый файл отдаётся без расхода времени на сжатие при каждом запросе.
5. Выберите уровень сжатия по задержке. Высокий уровень увеличивает время обработки динамического ответа.
6. Выполняйте сжатие в одном узле цепочки. Повторное сжатие уже сжатого ответа неэффективно.
7. Измерьте фактический коэффициент. Коэффициент зависит от состава ответа, поэтому проверяется на реальных данных.
Рекомендации:
- Различайте сжатие передачи и сжатие хранения. Сжатие ответа сокращает объём передачи, но не влияет на объём хранения исходных данных.
- Учитывайте потребление процессора. Сжатие каждого ответа расходует вычислительный ресурс, поэтому при высокой нагрузке уровень снижается.
- Проверяйте поддержку метода клиентом. Сервер отвечает методом из перечня клиента, поэтому отсутствие поддержки означает передачу без сжатия.
- Не сжимайте ответы с малым объёмом. Заголовок занимает фиксированный объём, поэтому выигрыш отсутствует.
- Фиксируйте перечень типов в конфигурации. Изменение состава типов влияет на долю сжатых ответов и нагрузку.
Практический сценарий: сжатие включено, но объём передачи не сократился
Контекст: сжатие включено в конфигурации, но объём передаваемых данных почти не изменился.
- Диагностика. Ответы состояли преимущественно из изображений и уже сжатых ресурсов. Сжатие выполнялось на каждом запросе, коэффициент был близок к единице, а время обработки выросло.
- Причина. Перечень типов содержимого включал бинарные типы без избыточности. Порог размера не был задан, поэтому сжатие применялось и к малым ответам, где заголовок занимал заметную долю.
- Действия. (а) Ограничили перечень типов текстовыми, исключив бинарные; (б) задали порог размера, ниже которого сжатие не выполняется; (в) включили предварительное сжатие для статических файлов, чтобы не расходовать время при каждом запросе; (г) добавили
Vary: Accept-Encodingдля корректного кэширования; (д) измерили объём передачи до и после изменения и убедились в сокращении. - Результат. Объём передачи текстовых ответов сократился, а сжатие бинарных данных не выполняется.
Вывод: сжатие применяется к типам содержимого с избыточностью и к ответам выше порога размера. Включение сжатия для всех типов расходует процессорное время без сокращения объёма передачи.
FAQ
Как клиент и сервер согласуют метод сжатия?
Клиент указывает поддерживаемые методы в Accept-Encoding, сервер выбирает один из перечня и указывает его в Content-Encoding.
Нужно ли сжимать изображения в ответе? Нет, изображения уже сжаты, поэтому повторное сжатие расходует время без уменьшения объёма.
Зачем нужен Vary: Accept-Encoding?
Кэш должен различать варианты ответа по методу сжатия, иначе клиенту может быть отдан вариант, который он не поддерживает.
Что даёт предварительное сжатие статики? Файл сжимается один раз при сборке, поэтому сервер отдаёт готовый файл без расхода времени на сжатие при каждом запросе.
Источники: nginx gzip modules, MDN Content-Encoding — ссылки в шапке.