Блог компании 3v-Hosting

Настройка gzip и Brotli в Nginx для сжатие сайта без лишней нагрузки на сервер

Администрирование

10 мин.


Скорость загрузки любого сайта в интернете зависит в том числе от объёма данных, которые сервер передаёт браузеру. К счастью, основные протоколы передачи данных через интернет, такие как HTML, CSS, JavaScript, JSON и другие текстовые данные хорошо сжимаются. Например файл размером 200 КБ после компрессии может занимать в несколько раз меньше. И конечно, не воспользоваться таким преимуществом было бы глупостью, поэтому все современные веб-серверы используют те или иные механизмы сжатия или компрессии трафика. Но сегодня мы поговорим о том, как этот конкретный механизм организован в одном из популярнейших веб-серверов современности, в Nginx.

В Nginx для компрессии чаще всего используют механизмы gzip и Brotli. Gzip уже встроен в Nginx и поддерживается он практически любым современным браузером. Механизм Brotli обычно сжимает текст чуть эффективнее, но для этого требуется установка отдельного модуля. Оба эти инструмента можно использовать и одновременно, например в таком случае браузер сообщает, какой алгоритм он поддерживает, а сервер выбирает подходящий и продолжает работу с выбранным механизмом.

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

 

 

 

 

Как вообще работает сжатие в Nginx

Когда браузер запрашивает страницу, то он сообщает серверу, какие алгоритмы сжатия он сам поддерживает. Для этого существует специальный заголовок Accept-Encoding, в котором передаётся такая информация:

Accept-Encoding: gzip, deflate, br

 

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

Content-Encoding: br

 

Браузер получает сжатые данные и сам их распаковывает. Для конечного приложения при таком механизме ничего не меняется и тот-же WordPress, Django, Laravel или другой backend продолжает отдавать обычный HTML или JSON.

 

Работа компрессии в Nginx

 

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

app.js
app.js.gz
app.js.br

В таком случае Nginx отдаёт уже готовый сжатый файл и не тратит ресурсы CPU на повторную компрессию. Такой подход удобен для сайтов и приложений, где статические ресурсы меняются крайне редко, например только при обновлении проекта.

 

Что такое gzip

Gzip - это встроенный в Nginx алгоритм сжатия с широкой поддержкой браузерами и другими HTTP-клиентами. Он хорошо подходит для HTML, CSS, JavaScript, JSON, XML и других текстовых данных.

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

 

Что такое Brotli

Brotli - это более новый алгоритм, который обычно сжимает текстовый контент сильнее gzip. Разница особенно заметна на крупных CSS и JavaScript-файлах.

Правда в стандартную сборку Nginx Brotli обычно не входит и для него нужен модуль ngx_brotli, поэтому сначала стоит проверить его наличие, о чем мы поговорим ниже.

Как мы уже упоминали выше, Gzip и Brotli можно включить одновременно. В этом случае, если клиент поддерживает Brotli, то сервер может использовать его, а для остальных остаётся gzip.

  gzip Brotli
Поддержка Nginx Встроен Нужен модуль
Совместимость Очень широкая Широкая в современных браузерах
Степень сжатия Хорошая Обычно выше
Динамическое сжатие Да Да
Предварительное сжатие .gz .br

Правда стоит учитывать, что для динамических ответов нет большого смысла гнаться за максимальным уровнем компрессии. У gzip и Brotli разумной отправной точкой обычно будет диапазон 4–6. Более тяжёлое сжатие интереснее для заранее подготовленной статики, где ресурс CPU тратится один раз при создании файла. Выкручивать-же ручку компрессии на максимум для всего будет нецелесообразным, так как уровень экономии трафика будет расти медленнее, чем будет расти нагрузка на CPU.

 

Какие файлы не нужно сжимать gzip и Brotli

Ещё раз повторим, что сжатие имеет смысл прежде всего для текстовых форматов. HTML, CSS, JavaScript, JSON, XML, SVG и TXT обычно уменьшаются очень хорошо, в разы.

Что-же касается JPEG, PNG, WebP, AVIF, видео и архивов, то они уже используют собственную компрессию, поэтому повторное сжатие редко заметно уменьшает их размер, зато требует процессорного времени. Это же относится и к PDF, которые тоже обычно нет смысла специально пропускать через gzip или Brotli.

Отсюда следует, что добавлять в инструкции gzip_types и brotli_types все доступные MIME-типы подряд не стоит.

 

 

 

Настройка сжатия в Nginx

 

Настройка gzip

Как вы знаете, Gzip уже входит в Nginx, поэтому обычно достаточно добавить несколько директив в блок http файла /etc/nginx/nginx.conf для его включения. Пример конфигурации может быть таким:

gzip on;
gzip_vary on;
gzip_comp_level 5;
gzip_min_length 1024;
​
gzip_types
    text/plain
    text/css
    text/xml
    application/javascript
    application/json
    application/xml
    application/rss+xml
    image/svg+xml;
  • gzip_comp_level 5 - для production этого уровня сжатия будет вполне достаточно, как мы обсудили выше.

  • gzip_min_length 1024 - отсекает слишком маленькие ответы, где компрессия почти ничего не даёт.

  • HTML отдельно добавлять в gzip_types не нужно: Nginx сжимает text/html по умолчанию.

 

Если статика уже сжата заранее, можно разрешить Nginx отдавать готовые .gz архивы:

gzip_static on;

Это удобно для CSS и JavaScript, которые меняются только при обновлении проекта.

 

Настройка Brotli

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

nginx -V 2>&1 | grep -i brotli

 

Если команда ничего не вернула, значит модуль нужно установить. В Ubuntu и Debian при использовании Nginx из системных репозиториев Brotli доступен отдельными пакетами. Пакет filter отвечает за динамическое сжатие, а пакет static - за выдачу заранее подготовленных .br-файлов.

Установить оба можно так:

sudo apt update
sudo apt install libnginx-mod-http-brotli-filter libnginx-mod-http-brotli-static

 

После установки проверьте конфигурацию и перезагрузите Nginx:

sudo nginx -t
sudo systemctl reload nginx

 

Если Nginx установлен из стороннего репозитория или собран вручную, то системные пакеты могут оказаться несовместимы с его ABI (Application Binary Interface). В таком случае модуль Brotli придётся устанавливать способом, предусмотренным для конкретной сборки Nginx, либо собирать вместе с ней.

После подключения модуля, его конфигурация похожа на конфигурацию gzip:

brotli on;
brotli_comp_level 5;
brotli_min_length 1024;
​
brotli_types
    text/plain
    text/css
    text/xml
    application/javascript
    application/json
    application/xml
    application/rss+xml
    image/svg+xml;

 

Для готовых .br используется:

brotli_static on;

Если проект собирается через CI/CD, то .gz и .br удобно создавать прямо на этапе сборки.

 

Проверяем, работает ли сжатие

После изменения конфигурации сначала проверяем синтаксис:

nginx -t

Если ошибок нет - применим её:

systemctl reload nginx

 

Теперь проверяем gzip:

curl -I -H "Accept-Encoding: gzip" https://example.com/

В ответе должен появиться заголовок:

Content-Encoding: gzip

 

Для Brotli:

curl -I -H "Accept-Encoding: br" https://example.com/

Ожидаемый результат:

Content-Encoding: br

 

Лучше проверить не только HTML, но и CSS или JavaScript, так как если главная страница сжимается, а app.js остаётся без Content-Encoding, то проблема может быть в MIME-типе или списке gzip_types / brotli_types.

Всё то же самое можно проверить и в браузере: DevTools → Network → нужный запрос → Response Headers.

 

Измерение реальной эффективности сжатия

Сам Content-Encoding показывает только факт работы компрессии, но насколько сильно она уменьшила ответ, из него не видно.

Для этого у gzip в Nginx есть специальная переменная:

$gzip_ratio

У ngx_brotli есть её аналог:

$brotli_ratio

 

Эти переменные можно добавить в access log и смотреть коэффициент сжатия уже на реальном трафике. Это будет правильнее, чем ставить максимальный уровень компрессии вслепую. Лучше проверить степень сжатия при различных установках уровня сжатия и если увеличение comp_level почти не уменьшает размер ответа, то дополнительная нагрузка на CPU смысла не имеет.

 

 

 

Траблшутинг: почему gzip или Brotli не работает

Если Content-Encoding в ответе нет, то обычно причина довольно простая. Давайте перечислим основные из них.

 

Ответ слишком маленький

При такой настройке:

gzip_min_length 1024;
brotli_min_length 1024;

Nginx не будет сжимать ответы меньше 1 КБ. Для проверки лучше брать крупный HTML, CSS или JavaScript-файл.

 

MIME-тип не попал в конфигурацию

Если нужного типа нет в gzip_types или brotli_types, ресурс останется несжатым.

Проверить тип ответа можно так:

curl -I https://example.com/app.js

Смотрите заголовок Content-Type и сверяйте его с конфигурацией Nginx.

 

Brotli не подключён

Директивы brotli on; и brotli_types работают только при наличии модуля.

Проверка:

nginx -V 2>&1 | grep -i brotli

Если вывода нет, текущая сборка Nginx, скорее всего, собрана без Brotli.

 

Nginx работает со старой конфигурацией

После изменений нужно проверить конфиг и перечитать его:

nginx -t
systemctl reload nginx

Без reload worker-процессы продолжат работать с прежними настройками.

 

Между Nginx и пользователем стоит CDN

CDN или внешний reverse proxy может сам сжимать ответы, менять Accept-Encoding или отдавать закешированную версию файла.

Тут имеет смысл проверять именно публичный ответ, который получает браузер, а при необходимости и отдельно обращаться к origin-серверу. Иначе легко искать проблему в Nginx там, где сжатие уже перехватил промежуточный слой.

 

 

 

 

Когда сжатие бесполезно или начинает мешать

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

Особенно спорным является использование максимальных уровней компрессии. Например если Brotli level 5 уменьшает ответ до 42 КБ, а level 11 - до 39 КБ, то несколько килобайт экономии могут стоить непропорционально дорого по CPU.

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

Со статикой дела обстоят гораздо проще. CSS и JavaScript можно заранее подготовить в .gz и .br, а Nginx будет только отдавать готовые файлы.

Есть ещё один редкий, но реальный нюанс. Сжатие HTTPS-ответов может участвовать в атаках класса BREACH, если в одном ответе оказываются секретные данные и содержимое, которое способен контролировать пользователь. Для обычной статики это не проблема, но страницы с токенами и другими чувствительными значениями требуют отдельной оценки.

 

 

 

 

FAQ

 

Что лучше для Nginx: gzip или Brotli?

Brotli обычно сжимает текст немного эффективнее. Но Gzip проще и уже встроен в Nginx. На практике их часто включают и используют одновременно.

 

Можно ли использовать gzip и Brotli вместе?

Да. Браузер сообщает поддерживаемые алгоритмы через Accept-Encoding, а Nginx выбирает подходящий вариант для ответа.

 

Какой gzip_comp_level ставить?

Для большинства сайтов достаточно 4-6. Значение 5 можно использовать как стартовое.

 

Какой brotli_comp_level выбрать?

Для динамического сжатия тоже разумно начать с 4-6. Высокие уровни больше подходят для заранее подготовленной статики.

 

Почему gzip не сжимает CSS или JavaScript?

Проверьте Content-Type, список gzip_types, значение gzip_min_length и не забудьте перечитать конфигурацию Nginx после изменений.

 

Нужно ли сжимать изображения?

Обычно нет. JPEG, PNG, WebP и AVIF уже используют собственное сжатие, поэтому дополнительный gzip или Brotli почти ничего не даст.

 

Можно ли использовать Brotli на небольшом VPS?

Можно. Тут важнее не объём RAM, а доступный CPU и текущая нагрузка. Максимальные уровни динамического Brotli на небольшом VPS обычно не нужны.

 

 

 

 

Выводы

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

Но вот на чём компрессия работает великолепно, так это практически на всём текстовом трафике сайта. В итоге HTML становится меньше, CSS становится меньше, JavaScript и JSON становятся меньше, поэтому пользователю приходится загружать меньше данных, а серверу - передавать существенно меньше трафика.

Для большинства конфигураций Nginx разумная схема довольно проста и заключается она в том, чтобы оставить gzip как совместимый базовый вариант, но добавить Brotli для клиентов, которые его поддерживают, а также не увлекаться максимальными уровнями динамического сжатия и по возможности использовать предварительно подготовленные .gz и .br для тяжёлой статики.

3v-Hosting Team

Автор

3v-Hosting Team

Команда 3v-Hosting - это группа преданных своему делу инженеров и операторов, которые занимаются созданием и поддержкой основы наших сервисов. Каждый день мы погружаемся в мир виртуальных и выделенных серверов, занимаясь всем, от развертывания и мониторинга до устранения реальных проблем, возникающих в производственных средах. Большинство наших статей основано на практическом опыте, а не просто на теории. Мы делимся своими наблюдениями о проблемах, с которыми сталкиваемся: перебоях в производительности, ошибках в настройке, тонкостях сетевых решений и архитектурных выборах, влияющих на стабильность и надежность. Наша миссия проста - мы хотим делиться знаниями, которые позволят вам управлять своими проектами с меньшим количеством неожиданностей и гораздо большей предсказуемостью.

Что такое epoll и почему Nginx такой быстрый
Что такое epoll и почему Nginx такой быстрый

Что такое epoll и почему Nginx считается одним из самых быстрых веб-серверов? Разбираем работу epoll, отличия от select и poll, событийную модель и настройку Ng...

14 мин