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

Я попытаюсь объяснить некоторые основы NGINX и то, как использовать его функции, чтобы получить максимальную производительность от ваших приложений и веб-сайтов. Большинство веб-разработчиков не используют NGINX для оптимизации своих веб-сайтов или приложений. Я понимаю, что в большинстве случаев и компании должны нести ответственность за DevOps. Проблема в том, что большинство функций и оптимизаций NGINX, о которых я расскажу в этой статье, тесно связаны с кодом вашего веб-сайта. Эти функции могут даже снизить производительность, если ваш веб-сайт не поддерживает их. Вот почему я думаю, что разработчикам важно хотя бы понимать эти технологии и термины, чтобы они могли их реализовать или изменить приложение, чтобы оно лучше работало в существующей конфигурации сервера.

Я не буду углубляться в некоторые функции NGINX, поскольку невозможно уместить все это в одном сообщении в блоге. Я попытаюсь объяснить некоторые основы и показать вам некоторые из вещей, которые я использую для повышения производительности. Я свяжусь с некоторыми дополнительными ресурсами в конце статьи, если вам нужны напоминания или если вы хотите узнать больше. Чтобы получить максимальную отдачу от этой статьи, вы должны иметь хоть какое-то представление о Linux и веб-серверах.

Вещи, которые я расскажу по порядку:

  1. NGINX - Основы и настройка
  2. SSL-сертификат и HTTPS
  3. HTTP / 2
  4. HTTP / 2 Push
  5. Кэширование на стороне клиента
  6. Сжатие
  7. Модуль Pagespeed
  8. NJS

1. Nginx - Основы и настройка

Перед реализацией любого из предложений вы должны знать, как установить NGINX и хотя бы некоторые из его основных принципов. Я расскажу об этих частях вкратце, потому что есть много ресурсов, которые содержат более подробную информацию. У NGINX тоже есть неплохая документация. Кроме того, все советы по установке предназначены исключительно для Ubuntu 18.04, но они, вероятно, будут работать в некоторых других версиях Ubuntu. Для большинства людей этих шагов должно быть достаточно. Иногда вам нужно выполнить дополнительные шаги и настройки в зависимости от вашего сервера. Если вы новичок, не делайте этого на существующих серверах с приложениями, которые находятся в разработке. Есть большая вероятность, что что-то пойдет не так, когда попробуешь эти вещи впервые. :)

Сначала установите NGINX на свой компьютер с Linux, используя следующие команды:

$ sudo apt update
$ sudo apt install nginx

После завершения процесса установки NGINX начнет обрабатывать весь HTTP-трафик. Вы можете проверить это, введя IP-адрес сервера в адресной строке браузера, и вы должны увидеть страницу NGINX по умолчанию. Если все в порядке, мы готовы добавить новый серверный блок (виртуальный хост) для нашего приложения. Виртуальный хост - это термин Apache. У NGINX нет виртуальных хостов, у него есть «серверные блоки».
Рекомендуемый подход - иметь отдельный файл конфигурации серверного блока для каждого из ваших приложений. Блоки сервера NGINX расположены в двух папках:

  1. /etc/nginx/sites-available, который содержит все конфигурации
  2. /etc/nginx/sites-enabled, который содержит включенные конфигурации

Сначала мы создадим файл конфигурации внутри sites-available, а затем создадим символическую ссылку на папку sites-enabled.

Перейдите в /etc/nginx/sites-available и создайте новый файл конфигурации:

vim example.conf

Теперь я объясню, что такое все директивы в базовом файле конфигурации, а затем мы будем опираться на него.

Простая конфигурация серверного блока NGINX:

listen и server_name directives будут использоваться NGINX, чтобы определить, какой из блоков сервера будет обслуживать запрос. listen определяет порт, которым в нашем случае является порт 80. По умолчанию HTTP переходит на порт 80, а HTTPS - на порт 443. server_name определяет имя хоста или IP-адрес, которому он должен соответствовать.
Если вы откройте свой URL-адрес в браузере, например Http://example.com, NGINX будет соответствовать порту 80, так как это HTTP, и проверит заголовок запроса Host, которым должен быть example.com. Исходя из этого, NGINX предполагает, что эта конфигурация серверного блока должна обрабатывать запрос.

Директива root указывает корневой каталог, который будет использоваться для поиска файла. Чтобы получить путь к запрошенному файлу, NGINX добавляет URI запроса (путь или часть URL-адреса после домена) к пути, указанному корневой директивой. Директива может быть размещена на любом уровне в http, server или location контекстах. В приведенном выше примере корневая директива определена для контекста сервера. Это применимо ко всем locationblocks, в которые не включена корневая директива.

loacation блоков будут проверяться по URI запроса. Необязательные модификаторы NGINX и регулярные выражения или литеральные строки могут использоваться для определения соответствия местоположения. В приведенном выше случае местоположение будет соответствовать всем запросам. На данный момент я буду использовать самое простое сопоставление местоположения, более сложным примером может быть случай, когда вы хотите обслуживать изображения из папки, которая не находится в serverroot. В этом случае вы можете написать другой блок местоположения с регулярным выражением, которое соответствует расширению файла изображения:

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

try_files в местоположении в основном сообщает NGINX, какой файл следует обслуживать после того, как он соответствует местоположению. В нашем случае мы сначала пытаемся загрузить файл в том виде, в котором он указан в запрошенном URI, и если этот файл не существует, мы обслуживаем index.html из корневого каталога.

Приведенной ниже конфигурации должно быть достаточно, чтобы вы начали. Просто не забудьте изменить его на свой домен и корневую папку.

Теперь нам нужно создать символическую ссылку на сохраненную конфигурацию в папку sites-enabled.
Мы делаем это с помощью следующей команды:

ln -s /etc/nginx/sites-available/example.conf /etc/nginx/sites-enabled

Это позволяет вам выборочно отключать / включать конфигурации серверных блоков, добавляя / удаляя символическую ссылку. NGINX будет загружать только файлы конфигурации, которые находятся в папке sites-enabled.

Теперь мы можем протестировать конфигурацию с помощью простой команды:

$ sudo nginx -t

NGINX сообщит вам, если что-то не так. Если вы получили «сообщение об успешном тестировании», вам необходимо перезагрузить NGINX, чтобы он принял новый файл конфигурации:

$ sudo service nginx reload

Не забывайте всегда использовать service nginx reload вместо service nginx restart. Это важно, потому что перезагрузка продолжит работу старых процессов, если обнаружит синтаксическую ошибку в конфигурации. С другой стороны, перезапуск убьет все процессы NGINX, и ваши серверные блоки перестанут работать, пока вы не исправите все ошибки, поэтому все ваши приложения, работающие на этом экземпляре NGINX, перейдут в автономный режим. Перезагрузка необходима в некоторых редких случаях, например. когда вы меняете директиву listen, имейте это в виду.

Если вы все сделали правильно, вы должны увидеть свой веб-сайт при вводе URL-адреса в браузере: http://example.com
Не забудьте заменить example.com на свое доменное имя. , а также убедитесь, что ваш домен указывает на правильный сервер. NGINX будет искать файл index.html в корневой папке, поэтому убедитесь, что он у вас есть. Теперь перейдем к более интересной части.

2. Сертификат SSL и HTTPS.

В наши дни каждый веб-сайт нуждается в сертификате SSL и HTTPS. Сегодня сертификаты SSL предоставляются бесплатно благодаря Let’s Encrypt, некоммерческой организации по сертификации, которая в настоящее время предоставляет сертификаты TLS 200 миллионам веб-сайтов. Они упрощают процесс, предоставляя программный клиент Certbot, который автоматизирует большинство необходимых шагов для NGINX.

Итак, давайте сначала установим Certbot для NGINX и Linux:

$ sudo add-apt-repository ppa:certbot/certbot
$ sudo apt-get update
$ sudo apt-get install python-certbot-nginx

После установки Certbot просто запустите команду ниже для домена, который указывает на ваш сервер.

$ sudo certbot --nginx -d example.com

Следуйте инструкциям и, когда вас спросят: «Выберите, следует ли перенаправлять HTTP-трафик на HTTPS, удаляя доступ по HTTP.», выберите 2: Перенаправить.
После этого Certbot изменит конфигурацию блока вашего сервера и перенаправит весь трафик на HTTPS. Откройте файл конфигурации сейчас, и вы должны увидеть это:

Вы можете видеть, что ваш первоначальный серверный блок изменен и что новый серверный блок создан. Ваш исходный серверный блок теперь прослушивает порт 443, который является HTTPS, а вновь созданный блок перенаправляет только HTTP-трафик на HTTPS.

Certbot также заботится об обновлении сертификатов. По умолчанию они действительны только в течение 90 дней, и Certbot продлевает их, когда срок действия истекает в течение тридцати дней.
Мы можем проверить, работает ли обновление, с помощью следующей команды:

$ sudo certbot renew --dry-run

Если вы не видите ошибок, автоматическое продление должно работать.

Наличие сертификата SSL и HTTPS также важно для следующего раздела, потому что HTTP / 2 не работает с небезопасным HTTP.

3. HTTP / 2

HTTP / 2 в настоящее время поддерживается почти 96% всех используемых веб-браузеров. Если у вас нет более старого проекта, который был полностью оптимизирован для получения максимальной отдачи от HTTP / 1, и вам не нужно поддерживать старые версии Internet Explorer и Opera Mini, нет причин не использовать HTTP / 2. .

Некоторые оптимизации HTTP / 1 считаются анти-шаблонами для сред HTTP / 2. Большинство из них связано с конкатенацией. Конкатенация - это процесс объединения файлов для уменьшения количества HTTP-запросов, которые не приносят пользу HTTP / 2. Примеры конкатенации: изображения спрайтов, связывание и встраивание CSS / JavaScript. Изображения спрайтов и их встраивание также могут уменьшить преимущества клиентского кеширования - если вы в конечном итоге обновите только одно из своих изображений, весь спрайт придется запрашивать снова, вместо того, чтобы запрашивать только обновленное изображение и сохранять другие в кеше.

Включение основных функций HTTP / 2 в NGINX довольно просто, вам просто нужно изменить директиву listen на:

listen 443 ssl http2;

Я попробовал несколько тестов производительности со многими изображениями / статическими ресурсами, и HTTP / 2 был в 2 раза быстрее в сети 4G и до 3 раз в сети 3G. Просто добавив метку http2 в свою директиву прослушивания, вы можете получить потрясающее повышение производительности, но будьте осторожны и проверяйте каждое изменение, которое вы делаете, поскольку все зависит от вашего веб-сайта или приложения.

4. HTTP / 2 Push

HTTP / 2 Server Push - еще одна полезная функция, которую немного сложнее реализовать. Push-сервер позволяет серверу предварительно загружать статические ресурсы, ожидая пользовательских запросов. В NGINX мы можем сделать это снова с помощью блока местоположения:

location = /index.html {
      http2_push /style.css;
      http2_push /image.jpg;
}

Это указывает NGINX отправлять style.css и image.jpg всякий раз, когда он получает запрос на index.html. Директива http2_push принимает один параметр, полный путь URI к файлу, который отправляется клиенту.
HTTP2 Push не очень полезен, если вам нужно жестко запрограммировать эти настройки и файлы на сервере. Это тоже не то, что я бы рекомендовал. Для этого есть два обходных пути. Первый - установить заголовки ссылок в вашем Node.js или другом приложении. NGINX будет автоматически отправлять ресурсы клиентам, если прокси-приложения включают HTTP-заголовок ответа Link. Этот заголовок проинструктирует NGINX предварительно загрузить указанные ресурсы. Чтобы включить эту функцию, добавьте http2_push_preload on; в конфигурацию NGINX:

Другой подход - иметь конфигурацию NGINX внутри GIT и Docker. Я могу осветить эту часть в следующей статье блога.

5. Кэширование на стороне клиента

С помощью NGINX мы можем установить заголовки ответов, чтобы сообщить клиенту (браузеру), что он может кэшировать определенный контент на определенное время. Это может значительно повысить производительность, поскольку браузер не будет запрашивать к серверу файлы, которые находятся в кеше. Вот как мы это делаем в NGINX:

location ~* \.(jpg|jpeg|png|gif|ico|css|js)$ {
      expires 30d;
      add_header Cache-Control “public”;
}

В этом примере у нас есть регулярное выражение местоположения, которое должно соответствовать всем изображениям, файлам JavaScript и CSS. Директива expires сообщает клиенту, что его кэшированный ресурс больше не будет действителен через 30 дней. Директива add_header добавляет к ответу HTTP-заголовок Cache-Control со значением public, что позволяет любому кэширующему серверу кэшировать ресурс. Если мы установим его в частный, только браузер сможет кэшировать значение.

6. Сжатие

Сжатие - это простой и эффективный способ сэкономить полосу пропускания и ускорить работу вашего сайта. Сжатие ответов часто значительно уменьшает размер передаваемых данных. Однако, поскольку сжатие происходит во время выполнения, оно также может привести к значительным накладным расходам на обработку, что может отрицательно сказаться на производительности. NGINX выполняет сжатие перед отправкой ответов клиентам, но не выполняет «двойное сжатие» ответов, которые уже сжаты (например, прокси-сервером).

Я покажу вам, как включить два самых популярных алгоритма сжатия - Gzip и Brotli. Gzip является модулем по умолчанию для NGINX, а Brotli - нет. Вы можете следовать инструкциям по установке на официальном модуле ngx_brotli Github. Если не хотите беспокоиться, просто удалите эту часть из конфигурации.

Brotli имеет впечатляющий прирост - до 25% по сравнению с сжатием Gzip. Он разработан Google, и в наши дни его поддерживают большинство браузеров. Также рекомендуется включить оба (GZIP и Brotli), чтобы старые браузеры по-прежнему получали сжатый контент. Это конфигурация с включенными Gzip и Brotli:

Директивы brotli_types & gzip_types включают сжатие на лету ответов для указанных типов MIME в дополнение к text/html, которые всегда сжимаются. Не рекомендуется включать сжатие для файлов изображений, а также для видео, PDF-файлов и других двоичных форматов. Использование сжатия на них не даст никаких дополнительных преимуществ и даже может увеличить их. В следующем разделе я покажу вам, как сжимать и оптимизировать изображения с помощью модуля Pagespeed.

Директивы brotli_comp_level & gzip_comp_level используются для указания уровня сжатия. Они просто определяют степень сжатия данных по шкале от 1 до 9 для GZIP и от 1 до 12 для Brotli, где 9 и 12 являются наиболее сжатыми. Рекомендуемый уровень - от 4 до 6, но все зависит от вашего сайта.

gzip_vary: on в основном просто добавляет заголовок Vary: Accept-Encoding. Он предназначен для предотвращения путаницы в клиентском кэше между сжатыми и несжатыми файлами. Если по какой-то причине у клиента есть несжатая версия файла в кэше, он будет знать, что не нужно запрашивать сжатую версию снова, а вместо этого просто использовать несжатый файл из кеша. В конце концов, вы также предотвращаете предоставление несжатой версии пользователю, который поддерживает gzip, и наоборот.

7. Модуль PageSpeed

Это модуль NGINX с открытым исходным кодом, который автоматически оптимизирует ваш сайт, и немногие об этом знают. Он создан Google и реализует большинство рекомендаций Google по скорости загрузки страниц. Это может значительно повысить производительность и SEO. Я много раз злоупотреблял этим модулем и буду продолжать это делать! Если вам нужно быстро улучшить производительность веб-сайта, просто настройте его за несколько часов, и вы получите большие улучшения! Трудно поверить, насколько легко можно превратить сверхмедленные веб-сайты в высокопроизводительные, просто используя этот модуль.

Процесс настройки не так прост, но он того стоит, когда вы видите, насколько он приносит пользу. Вы можете следовать этим инструкциям s о том, как его установить, и я дам вам несколько советов по его настройке.

Это конфигурация серверного блока с некоторыми параметрами конфигурации PageSpeed:

Он имеет множество параметров конфигурации, и вы должны настраивать их для каждого веб-сайта отдельно. Возможно, ваш стек внешнего интерфейса уже выполняет некоторые из этих оптимизаций, и это может показаться нелогичным, если вы не синхронизируете все вместе. Если вы используете HTTP2, вам следует отключить все параметры конкатенации или, по крайней мере, разбивать файлы на более мелкие куски. Вы должны сделать это в NGINX и, например, в Webpack.
Я попытаюсь объяснить несколько директив PageSpeed, которые я использовал выше, но вам действительно стоит проверить официальную документацию и посмотреть, какие варианты лучше всего подходят для вашего веб-сайта.

Директива pagespeed RewriteLevel PassThrough отключает RewriteLevel CoreFilters. Это означает, что вам нужно вручную включить каждый фильтр, который вы хотите включить. Он предлагает три уровня перезаписи для упрощения настройки: PassThrough, CoreFilters и OptimizeForBandwidth.
Набор CoreFilters содержит фильтры, которые, по мнению группы PageSpeed, безопасны для большинства веб-сайтов. При использовании набора CoreFilters по мере обновления PageSpeed ​​новыми фильтрами ваш сайт станет быстрее. Параметр OptimizeForBandwidth обеспечивает более надежную гарантию безопасности и подходит в качестве настройки по умолчанию для использования с сайтами, которые не знают о PageSpeed. Лично я предпочитаю вручную настраивать каждый фильтр и потом тестировать его. Вы также можете попробовать использовать CoreFilters и OptimizeForBandwidth и посмотреть, работает ли это лучше для вас.

pagespeed EnableFilters recompress_images - это группа фильтров, состоящая из директив convert_gif_to_png, convert_jpeg_to_progressive, convert_jpeg_to_webp, convert_png_to_jpeg, jpeg_subsampling, recompress_jpeg, recompress_png, recompress_webp, strip_image_color_profile и strip_image_meta_data. Вы можете проверить документацию по каждой из этих директив. По сути, он оптимизирует все размещенные изображения и обслуживает наилучший формат в зависимости от поддержки браузера. Например, вы можете загрузить неоптимизированное изображение в формате jpeg, и если клиент запросит это изображение с помощью Google Chrome, PageSpeed ​​предоставит его оптимизированным в формате webp, поскольку Chrome поддерживает его. Вероятно, он будет в 10 раз меньше оригинала.

pagespeed FileCachePath сообщает Pagespeed, какую папку следует использовать для генерируемого кэша. Pagespeed будет кэшировать все статические ресурсы, если вы настроите его для этого.
Фильтр extend_cache перезаписывает URL-ссылки на HTML-странице, чтобы включить хэш содержимого ресурса (если rewrite_css включен, тогда URL-адреса изображений в CSS тоже будет переписан). Таким образом, если владельцы сайта изменят содержимое ресурса, URL-адрес перезаписанного ресурса также изменится. На старое содержимое в кэше браузера пользователя больше не будут ссылаться, потому что оно не будет соответствовать новому имени. Если владельцы сайта изменят логотип, PageSpeed ​​заметит это в течение 5 минут и начнет предоставлять пользователям другой URL-адрес. Но если контент не изменится, то хеш не изменится, и копия в браузере каждого пользователя останется действительной и доступной.

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

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

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

## ADMIN
pagespeed Statistics on;
pagespeed StatisticsLogging on;
pagespeed GlobalAdminPath /pagespeed_admin;

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

9. Язык сценариев NJS

Эта часть малоизвестна даже в сообществе DevOps, и она будет наиболее интересна разработчикам JavaScript. Команда NGINX решила добавить дополнительные параметры сценариев для своих файлов конфигурации. Они сделали это, написав свой собственный интерпретатор на JavaScript, который предоставляет объекты, методы и свойства для расширения функциональности NGINX.

Некоторые из причин, по которым они выбрали JavaScript вместо других языков:

  • JavaScript имеет синтаксис, подобный C, который очень похож на файлы конфигурации NGINX.
  • JavaScript использует фигурные скобки для разных блоков, что также относится к NGINX.
  • JavaScript управляется событиями, как и NGINX

Некоторые варианты использования:

  • Комплексный контроль доступа и проверки безопасности в NJS до того, как запрос достигнет вышестоящего сервера.
  • Управление заголовками ответов
  • Написание гибких асинхронных обработчиков контента и фильтров.

Простой пример Hello World с NJS:

# nginx.conf example
events {}
http {
    js_import http.js;
    js_content http.hello;
}
# http.js example
function hello(r) {
 r.return(200, “Hello world!”);
}
export default {hello};

Вы можете найти больше примеров и вариантов использования по этой ссылке. Один из вариантов использования, над которым я планирую работать, - это Dynamic HTTP2 Server Push. Я напишу еще одну статью в блоге именно об этом, когда я как следует протестирую решение.

Важно отметить, что он не поддерживает большинство спецификаций ES6 и модулей JavaScript / стороннего кода. Команда NGINX говорит, что это в основном из-за производительности, например. Спецификации ECMAScript требуют кодировки UTF-16, а NJS использует UTF-8, которому требуется в 2 раза меньше байтов для любого фрагмента данных. Это показывает, насколько они действительно заботятся о производительности. Если вы когда-нибудь заметите, что вам не хватает некоторых функций NGINX, стоит проверить NJS.

Подводить итоги

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

Я предлагаю вам прочитать официальную документацию по всем терминам, которые вы не совсем понимаете, и, еще раз, очень важно тестировать каждое вносимое вами изменение. Ниже вы можете увидеть полезные ресурсы и документацию по затронутым темам:

Спасибо за чтение. Прокомментируйте, аплодируйте или поделитесь этим с друзьями! Также большое спасибо Ане Шелер за дизайн!