Повышение производительности сайта с помощью gzip и Nginx
Производительность сайта отчасти зависит от размера файлов, которые должен загрузить браузер посетителя. Уменьшив размер передаваемых файлов, вы можете сделать ваш сайт быстрее. Кроме того, это может удешевить ваш сайт для тех посетителей, которые платят за использование полосы пропускания по лимитным соединениям.
gzip – это популярная программа для сжатия данных. Вы можете настроить веб-сервер Nginx для сжатия загружаемых файлов через gzip. Затем эти файлы распакуют браузеры – и сайт работает без каких-либо потерь, но имеет существенное преимущество: между веб-сервером и браузером передается меньший объем данных. Еще одна хорошая новость: сжатие широко поддерживается всеми основными браузерами, и не использовать ее нет причин.
Из-за особенностей работы сжатия в целом и gzip в частности, некоторые файлы сжимаются лучше, чем другие. Например, текстовые файлы сжимаются очень хорошо (часто их можно сделать в два раза меньше). А изображения – файлы JPEG или PNG – уже сжаты по своей природе, и повторное сжатие с помощью gzip не дает практически никаких результатов. Конечно, операция сжатия файлов использует ресурсы сервера, поэтому лучше сжимать только те файлы, размер которых существенно уменьшится.
В этом мануале вы узнаете, как настроить Nginx для поддержки сжатия gzip. Это уменьшит размер контента, отправляемого посетителям вашего сайта, и повысит его производительность.
Требования
- Сервер Ubuntu 20.04, а также пользователь с привилегиями sudo. Вы можете узнать, как подготовить свой сервер, следуя этому руководству.
- Установка Nginx на сервере (следуйте руководству Установка Nginx в Ubuntu 20.04).
1: Создание тестовых файлов
На начальном этапе мы создадим несколько тестовых файлов в стандартном каталоге Nginx. Мы будем использовать эти файлы позже, чтобы проверить поведение Nginx при сжатии gzip и узнать, имеет ли сжатие желаемый эффект.
Чтобы определить, какой тип файла обслуживается по сети, Nginx не анализирует все его содержимое – это было бы слишком долго. Вместо этого он смотрит на расширение и определяет MIME-тип файла, который определяет его цель.
Это значит, что содержимое наших тестовых файлов не имеет значения. Называя файлы соответствующим образом, мы можем обмануть Nginx, заставить его думать, что, например, один пустой файл является изображением, а другой – таблицей стилей.
Создайте файл test.html в каталоге Nginx, используя truncate. Расширение этого файла означает, что это HTML-страница:
sudo truncate -s 1k /var/www/html/test.html
Давайте создадим еще несколько тестовых файлов с другими расширениями – jpg, css и js.
sudo truncate -s 1k /var/www/html/test.jpg
sudo truncate -s 1k /var/www/html/test.css
sudo truncate -s 1k /var/www/html/test.js
Следующим шагом будет проверка того, как Nginx ведет себя при обработке запрошенных файлов (на примере тех файлов, что мы только что создали).
2: Проверка стандартного поведения Nginx
Давайте проверим как обрабатывается HTML-файл test.html – со сжатием или без. Команда запрашивает файл с сервера Nginx и через HTTP-заголовок (Accept-Encoding: gzip) указывает, что можно использовать сжатый с помощью gzip контент:
curl -H «Accept-Encoding: gzip» -I http://localhost/test.html
В ответ вы должны увидеть несколько заголовков HTTP-ответа:
Date: Tue, 09 Feb 2021 19:04:25 GMT
Last-Modified: Tue, 09 Feb 2021 19:03:41 GMT
В последней строке вы можете увидеть заголовок Content-Encoding: gzip. Это говорит нам о том, что для отправки этого файла использовалось сжатие. Произошло это потому, что в Nginx сжатие включено автоматически – то есть даже в новой установке Ubuntu.
Однако по умолчанию Nginx сжимает только файлы HTML. Все остальные файлы будут обслуживаться без сжатия, что не совсем хорошо. Чтобы убедиться в этом, вы можете запросить тестовый файл test.jpg:
curl -H «Accept-Encoding: gzip» -I http://localhost/test.jpg
Результат будет немного отличаться от предыдущего:
Date: Tue, 09 Feb 2021 19:05:49 GMT
Last-Modified: Tue, 09 Feb 2021 19:03:45 GMT
В выводе заголовок Content-Encoding: gzip отсутствует, а это означает, что файл был обработан без сжатия.
Вы можете повторить тест с таблицей стилей CSS:
curl -H «Accept-Encoding: gzip» -I http://localhost/test.css
И снова в выводе не будет упоминания о сжатии:
Date: Tue, 09 Feb 2021 19:06:04 GMT
Last-Modified: Tue, 09 Feb 2021 19:03:45 GMT
Давайте настроим Nginx так, чтобы он мог сжимать все типы файлов, для которых полезно использовать gzip.
3: Настройка gzip в Nginx
Чтобы изменить стандартную конфигурацию gzip в Nginx, откройте главный конфигурационный файл Nginx в nano или в другом текстовом редакторе:
sudo nano /etc/nginx/nginx.conf
Найдите раздел настроек gzip, который выглядит так:
# gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript;
Как видите, сжатие gzip действительно включено (директива gzip on), но некоторые дополнительные параметры закомментированы знаком # и не используются. Давайте внесем в этот раздел несколько изменений:
- Раскомментируйте все закомментированные строки (удалив # в начале строки), чтобы активировать их.
- Добавьте gzip_min_length 256; эта директива указывает Nginx не сжимать файлы размером менее 256 байт. Сжимать очень маленькие файлы практически не имеет смысла.
- Добавьте в директиву gzip_types другие типы файлов (веб-шрифты, иконки, XML-каналы, структурированные данные JSON и изображения SVG).
После внесения этих изменений раздел должен выглядеть так:
Настройка модуля GZIP в NGINX
GZIP — популярная программа сжатия данных.
Выполним настройку NGINX на использование gzip для сжатия файлов, которые он обслуживает «на лету».
Эти файлы затем распаковываются браузерами, которые поддерживают его при извлечении без каких-либо потерь, но с выгодой для передачи меньшего количества данных между веб-сервером и браузером.
Сжатие файлов использует ресурсы сервера, поэтому лучше всего сжимать только те файлы, которые значительно уменьшат размер в результате. Текстовые файлы сжимаются хорошо, JPEG или PNG уже сжаты по своей природе и большого результата при сжатии их GZIP можно не ожидать.
Модуль GZIP по умолчанию установлен в NGINX, необходимо включить его и настроить.
Создаем новый конфигурационный файл /etc/nginx/conf.d/gzip.conf :
gzip on;
gzip_disable «msie6»;
gzip_vary on;
gzip_proxied any;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 1100;
gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;
gzip on — включаем поддержку GZIP сжатия.
gzip_disable «msie6» — исключаем IE6 из браузеров, которые будут получать сжатые файлы. (не поддерживает GZIP)
gzip_buffers — задаёт число и размер буферов, в которые будет сжиматься ответ. По умолчанию размер одного буфера равен размеру страницы. В зависимости от платформы это или 4K , или 8K .
gzip_proxied — сжимать данные ответов для proxy-серверов;
gzip_vary on — включает добавление в ответ заголовка «Vary: Accept-Encoding» , для IE4-6 это приведёт к не кешированию данных из-за бага.
gzip_comp_level 6 — устанавливаем, сколько файлов будет сжато. Чем выше число, тем выше уровень сжатия и использование ресурсов. уровень сжатия, 1 — минимальное, 9 — максимальное;
gzip_http_version 1.1 — директива используется для ограничения сжатия gzip для браузеров, поддерживающих протокол HTTP/1.1. Если браузер не поддерживает его, вероятно, что он не поддерживает и gzip.
gzip_min_length 1100 — сообщаем NGINX не сжимать файлы размером менее 256 байт.
gzip_types — отображает все типы MIME, которые будут сжаты. В этом случае список включает страницы HTML, таблицы стилей CSS, файлы Javascript и JSON, файлы XML, значки, изображения SVG и веб-шрифты.
Для применения настроек перезагрузим NGINX.
$ curl -H «Accept-Encoding: gzip» -I https://bogachev.biz
HTTP/1.1 200 OK
Server: nginx
Date: Mon, 30 Oct 2017 20:26:17 GMT
Content-Type: text/html; charset=UTF-8
Last-Modified: Tue, 24 Oct 2017 20:02:54 GMT
Connection: keep-alive
Vary: Accept-Encoding
ETag: W/«59ef9c6e-15be3»
Strict-Transport-Security: max-age=31536000;
Content-Security-Policy-Report-Only: default-src https:; script-src https: ‘unsafe-eval’ ‘unsafe-inline’; style-src https: ‘unsafe-inline’; img-src https: data:; font-src https: data:; report-uri /csp-report
X-Frame-Options: DENY
X-Content-Type-Options: nosniff
Content-Encoding: gzip
Compression and Decompression
Compress server responses, or decompress them for clients that don’t support compression, to improve delivery speed and reduce overhead on the server.
This section describes how to configure compression or decompression of responses, as well as sending compressed files.
Introduction
Compressing responses often significantly reduces the size of transmitted data. However, since compression happens at runtime it can also add considerable processing overhead which can negatively affect performance. NGINX performs compression before sending responses to clients, but does not “double compress” responses that are already compressed (for example, by a proxied server).
Enabling Compression
To enable compression, include the gzip directive with the on parameter.
By default, NGINX compresses responses only with MIME type text/html . To compress responses with other MIME types, include the gzip_types directive and list the additional types.
gzip_types text/plain application/xml;
To specify the minimum length of the response to compress, use the gzip_min_length directive. The default is 20 bytes (here adjusted to 1000):
By default, NGINX does not compress responses to proxied requests (requests that come from the proxy server). The fact that a request comes from a proxy server is determined by the presence of the Via header field in the request. To configure compression of these responses, use the gzip_proxied directive. The directive has a number of parameters specifying which kinds of proxied requests NGINX should compress. For example, it is reasonable to compress responses only to requests that will not be cached on the proxy server. For this purpose the gzip_proxied directive has parameters that instruct NGINX to check the Cache-Control header field in a response and compress the response if the value is no-cache , no-store , or private . In addition, you must include the expired parameter to check the value of the Expires header field. These parameters are set in the following example, along with the auth parameter, which checks for the presence of the Authorization header field (an authorized response is specific to the end user and is not typically cached):
gzip_proxied no-cache no-store private expired auth;
As with most other directives, the directives that configure compression can be included in the http context or in a server or location configuration block.
The overall configuration of gzip compression might look like this.
server < gzip on; gzip_types text/plain application/xml; gzip_proxied no-cache no-store private expired auth; gzip_min_length 1000; . >
Enabling Decompression
Some clients do not support responses with the gzip encoding method. At the same time, it might be desirable to store compressed data, or compress responses on the fly and store them in the cache. To successfully serve both clients that do and do not accept compressed data, NGINX can decompress data on the fly when sending it to the latter type of client.
To enable runtime decompression, use the gunzip directive.
location /storage/ < gunzip on; . >
The gunzip directive can be specified in the same context as the gzip directive:
server < gzip on; gzip_min_length 1000; gunzip on; . >
Note that this directive is defined in a separate module that might not be included in an NGINX Open Source build by default.
Sending Compressed Files
To send a compressed version of a file to the client instead of the regular one, set the gzip_static directive to on within the appropriate context.
In this case, to service a request for /path/to/file, NGINX tries to find and send the file /path/to/file.gz. If the file doesn’t exist, or the client does not support gzip, NGINX sends the uncompressed version of the file.
Note that the gzip_static directive does not enable on-the-fly compression. It merely uses a file compressed beforehand by any compression tool. To compress content (and not only static content) at runtime, use the gzip directive.
This directive is defined in a separate module that might not be included in an NGINX Open Source build by default.