Новинка Виртуальный VDS сервер в Финляндии от 390р
Выберите продукт

Динамическое сжатие в Nginx и Apache: gzip/brotli, уровни, буферы и исключения

Разбираем динамическое сжатие на веб-серверах: когда включать gzip и brotli, какие уровни и буферы выбрать, что исключать из типов, как избежать двойного сжатия и проблем со стримом. Дадим готовые конфиги, чек‑лист и команды проверки.
Динамическое сжатие в Nginx и Apache: gzip/brotli, уровни, буферы и исключения

Динамическое сжатие экономит трафик и ускоряет отдачу HTML, CSS, JS и API-ответов без изменения кода приложения. Но «включить gzip/brotli» — лишь полдела. Важно подобрать уровни сжатия под CPU, настроить буферы, списки типов, исключить уже сжатые форматы, корректно работать с Vary/ETag и не сломать стриминг (SSE) и загрузки. Ниже — практический разбор для Nginx и Apache с готовыми конфигурациями и комментариями.

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

Даже в 2025-м большинство текстовых форматов выигрывает от сжатия: HTML, JSON, CSS, JS, XML, SVG, TTF/OTF. Экономия трафика снижает TTFB на медленных сетях, сокращает расходы и нагрузку на каналы. При этом нельзя слепо «жимать всё»: многие форматы уже сжаты (WOFF2, JPEG/PNG/WebP/AVIF, ZIP, PDF, видео/аудио), а некоторые сценарии ломаются от компрессии (SSE, иногда проксирование потоков).

Как работает выбор алгоритма

Браузер сообщает поддерживаемые алгоритмы в заголовке Accept-Encoding. Современный приоритет: сначала br (Brotli), затем gzip. Если сервер умеет brotli — отдаем brotli; иначе gzip; если ничего — несжатый ответ. Обязательно добавляйте Vary: Accept-Encoding, чтобы кэши и CDN хранили корректные варианты.

Схема выбора gzip и brotli по заголовку Accept-Encoding

Nginx: включаем gzip правильно

Базовый набор для production:

gzip on;
gzip_comp_level 5;
gzip_min_length 512;
gzip_vary on;
gzip_http_version 1.1;
gzip_proxied expired no-cache no-store private auth no_last_modified no_etag;
gzip_buffers 32 8k;

# Список типов (text/html сжимается всегда)
gzip_types
    text/plain
    text/css
    text/xml
    text/javascript
    application/javascript
    application/json
    application/xml
    application/rss+xml
    application/atom+xml
    application/manifest+json
    image/svg+xml
    font/ttf
    font/otf;

# Совместимость
gzip_disable "msie6";

Рекомендуемые уровни и длины

  • gzip_comp_level: 4–6 — оптимум для динамики. 1–3 экономнее по CPU, но слабее эффект; 7–9 почти не дают выгоды, а нагрузка растёт.
  • gzip_min_length: 256–1024. Короткие ответы не стоит сжимать — накладные расходы съедят выгоду.

Буферы gzip: сколько и зачем

gzip_buffers задаёт число и размер внутренних буферов компрессора. Для страниц и JSON адекватно 16–32 буфера по 8k. Если видите «gzip buffer error» или разрывы при отдаче больших HTML, увеличьте число буферов. Помните, что буферы выделяются из памяти рабочего процесса.

Исключения в Nginx

  • Не сжимайте заранее сжатые форматы: jpg jpeg png webp avif gif svgz mp4 mkv webm mp3 ogg woff woff2 pdf zip gz bz2 xz 7z.
  • Не сжимайте SSE: тип text/event-stream оставляйте вне gzip_types, иначе сломаете потоковую доставку событий.
  • Аккуратно с проксированием: если апстрим уже прислал Content-Encoding: gzip, не выполняйте повторное сжатие. Для конверсии можно включить модуль gunzip:
gunzip on;
# Nginx примет gzip от апстрима, распакует и при наличии brotli отдаст клиенту br.

Nginx: brotli — современный выбор

Динамический brotli обычно даёт лучшую степень сжатия, чем gzip, но дороже по CPU на высоких уровнях. Для большинства сайтов достаточно 4–6.

# Требуется модуль brotli для Nginx
brotli on;
brotli_comp_level 5;
brotli_min_length 512;

brotli_types
    text/plain
    text/css
    text/xml
    text/javascript
    application/javascript
    application/json
    application/xml
    application/rss+xml
    application/atom+xml
    application/manifest+json
    image/svg+xml
    font/ttf
    font/otf;

Сочетание brotli и gzip

Включайте оба алгоритма: клиентам с br отдавайте brotli, остальным — gzip. Для статических файлов полезны предсжатые артефакты: gzip_static on; и brotli_static on; — Nginx возьмёт .br/.gz, если они лежат рядом, разгружая CPU.

Apache: mod_deflate (gzip) и mod_brotli

В Apache gzip реализован через mod_deflate, brotli — через mod_brotli. Ниже — типовая конфигурация с логикой исключений, корректным Vary и адекватными уровнями.

<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/css text/xml text/javascript application/javascript application/json application/xml application/rss+xml application/atom+xml application/manifest+json image/svg+xml font/ttf font/otf
    DeflateCompressionLevel 5
    # Буферы/окна zlib (меняйте только при симптомах)
    DeflateWindowSize 15
    DeflateMemLevel 8
    DeflateBufferSize 8192

    # Исключаем уже сжатые и медийные форматы
    SetEnvIfNoCase Request_URI \.(?:jpg|jpeg|png|webp|avif|gif|svgz|mp4|mkv|webm|mp3|ogg|woff|woff2|pdf|zip|gz|bz2|xz|7z)$ no-gzip dont-vary
    # Исключаем SSE
    SetEnvIfNoCase Content-Type ^text/event-stream$ no-gzip

    # Корректный Vary
    Header append Vary Accept-Encoding env=!dont-vary
</IfModule>

<IfModule mod_brotli.c>
    AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/css text/xml text/javascript application/javascript application/json application/xml application/rss+xml application/atom+xml application/manifest+json image/svg+xml font/ttf font/otf
    BrotliCompressionQuality 5
    BrotliWindowSize 16
    BrotliSendVary On
    BrotliAlterETag AddSuffix

    # Те же исключения, что и для gzip
    BrotliDisable for=env=no-gzip
</IfModule>

Буферы и память в Apache

  • DeflateBufferSize, DeflateMemLevel, DeflateWindowSize — тонкая настройка zlib; меняйте только при реальных симптомах (фрагментация, ошибки компрессии, повышенные задержки).
  • Для brotli основная ручка — BrotliCompressionQuality; увеличивать BrotliWindowSize обычно не требуется.

Сравнение конфигураций сжатия для Nginx и Apache

Что обязательно исключать

  • Медиа и архивы: уже сжаты или несжимаемы — вы теряете CPU, не выигрывая скорость.
  • SSE и любые долгие стримы: компрессия ломает семантику «мгновенных» событий и добавляет задержки из‑за буферизации.
  • Вторичное сжатие: если апстрим отдал Content-Encoding, не сжимайте снова. В Nginx используйте gunzip on; для конверсии gzip → brotli или отдавайте «как есть».
  • Короткие ответы: меньше 256–512 байт не стоит сжимать.

Про производительность и уровни

Компрессия — это CPU. На серверах с ограниченным количеством ядер держите уровни в «середине»: gzip 4–5, brotli 4–5. Для API с большими JSON разумно 5–6, если хватает CPU. Высокие уровни 8–11 оправданы только для статически предсжатых артефактов (сборка фронтенда), а не для динамики. Если вы упираетесь в процессор на шаред-площадке, рассмотрите перенос на VDS, чтобы контролировать ресурсы и изоляцию.

FastFox VDS
Облачный VDS-сервер
Виртуальные серверы с быстрым запуском и гибкой конфигурацией от 390₽ / мес
Доступные локации
Россия Нидерланды Финляндия

Кэширование, Vary и ETag

Всегда отправляйте Vary: Accept-Encoding. Иначе кэш может отдать несоответствующий вариант клиенту. В Apache полезен BrotliAlterETag AddSuffix, чтобы отличались ETag’и. В Nginx при etag on; достаточно корректного Vary и отсутствия ручной подмены ETag. Подробно о сроках хранения и валидаторах — в материале настройка Cache-Control и ETag.

Проверка и мониторинг

  • Быстрая проверка ответов:
curl -sI -H 'Accept-Encoding: br' https://example.com/
curl -sI -H 'Accept-Encoding: gzip' https://example.com/
curl -sI https://example.com/
  • Ищите заголовки Content-Encoding, Vary, Content-Length или Transfer-Encoding.
  • Логирование эффективности в Nginx:
log_format main '$remote_addr - $request $status $body_bytes_sent CE=$sent_http_content_encoding GR=$gzip_ratio';
access_log /var/log/nginx/access.log main;

$gzip_ratio покажет, на сколько уменьшился размер. Для brotli метрики удобнее снимать APM/прокси/CDN или нагрузочными тестами. Если раздаёте большие файлы по диапазонам, проверьте корректность работы с Range — см. краткий разбор в статье HTTP Range и кэш.

Частые ошибки и как их избежать

  • Двойное сжатие: апстрим уже отдал gzip, а фронтенд-сервер пытается сжать снова. Решение: проверяйте Content-Encoding, используйте gunzip on; либо отключайте сжатие на апстриме.
  • Забыли Vary: кэш портит варианты. Всегда добавляйте Vary: Accept-Encoding.
  • Слишком высокий уровень: CPU уходит в компрессию, растёт TTFB. Снижайте уровни до 4–5.
  • Сжатие SSE: события приходят рывками или залипают. Исключайте text/event-stream.
  • Сжатие медиа: растёт нагрузка, пользы ноль. Держите чёрный список расширений/типов.

Минимальные готовые профили

Nginx — сбалансированный профиль

gzip on;
gzip_comp_level 5;
gzip_min_length 512;
gzip_vary on;
gzip_http_version 1.1;
gzip_proxied expired no-cache no-store private auth no_last_modified no_etag;
gzip_buffers 32 8k;
gzip_types text/plain text/css text/xml text/javascript application/javascript application/json application/xml application/rss+xml application/atom+xml application/manifest+json image/svg+xml font/ttf font/otf;

# Brotli как приоритетный алгоритм
gunzip on;
brotli on;
brotli_comp_level 5;
brotli_min_length 512;
brotli_types text/plain text/css text/xml text/javascript application/javascript application/json application/xml application/rss+xml application/atom+xml application/manifest+json image/svg+xml font/ttf font/otf;

# Предсжатые статические ассеты
brotli_static on;
gzip_static on;

Apache — сбалансированный профиль

<IfModule mod_deflate.c>
    AddOutputFilterByType DEFLATE text/html text/plain text/css text/xml text/javascript application/javascript application/json application/xml application/rss+xml application/atom+xml application/manifest+json image/svg+xml font/ttf font/otf
    DeflateCompressionLevel 5
    Header append Vary Accept-Encoding
    SetEnvIfNoCase Request_URI \.(?:jpg|jpeg|png|webp|avif|gif|svgz|mp4|mkv|webm|mp3|ogg|woff|woff2|pdf|zip|gz|bz2|xz|7z)$ no-gzip dont-vary
    SetEnvIfNoCase Content-Type ^text/event-stream$ no-gzip
</IfModule>

<IfModule mod_brotli.c>
    AddOutputFilterByType BROTLI_COMPRESS text/html text/plain text/css text/xml text/javascript application/javascript application/json application/xml application/rss+xml application/atom+xml application/manifest+json image/svg+xml font/ttf font/otf
    BrotliCompressionQuality 5
    BrotliSendVary On
    BrotliAlterETag AddSuffix
    BrotliDisable for=env=no-gzip
</IfModule>

Чек-лист внедрения

  1. Соберите список MIME-типов для сжатия. Уберите медиа и архивы.
  2. Выберите уровни: gzip 4–6, brotli 4–6 для динамики.
  3. Настройте буферы: в Nginx gzip_buffers 16–32×8k; в Apache оставляйте дефолт, меняйте только при симптомах.
  4. Включите Vary: Accept-Encoding. Для Apache добавьте BrotliAlterETag при использовании brotli.
  5. Сделайте исключения для SSE (text/event-stream), коротких ответов и заранее сжатых форматов.
  6. При проксировании решите, где происходит сжатие. Во избежание дубля включите gunzip или отключите сжатие на апстриме.
  7. Проверьте ответы cURL, прогоните нагрузочные тесты, посмотрите на CPU и $gzip_ratio.
  8. Добавьте gzip_static/brotli_static для тяжёлых ассетов фронтенда.

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

Поделиться статьей

Вам будет интересно

Как безопасно выполнить bootstrap MariaDB Galera после полного останова

Как безопасно выполнить bootstrap MariaDB Galera после полного останова

После одновременной остановки всех узлов Galera обычного запуска MariaDB недостаточно. Сначала найдите сервер с последней транзакц ...
CoreDNS в Kubernetes: исправляем CrashLoopBackOff, SERVFAIL и DNS-петлю

CoreDNS в Kubernetes: исправляем CrashLoopBackOff, SERVFAIL и DNS-петлю

Разберём, почему CoreDNS перезапускается или отвечает SERVFAIL, как обнаружить замкнутую пересылку DNS-запросов, проверить доступн ...
Apache Kafka KRaft на VDS: отдельные controller и broker

Apache Kafka KRaft на VDS: отдельные controller и broker

Соберём новый Kafka-кластер без ZooKeeper на шести Linux VDS: три узла controller образуют отказоустойчивый metadata quorum, а три ...