Оптимизация производительности Nginx: Советы для ускорения веб-сайтов

Раскройте весь потенциал вашего сервера Nginx с помощью нашего всеобъемлющего руководства по оптимизации производительности. Узнайте, как точно настроить рабочие процессы, внедрить надежные стратегии кеширования, включить эффективное сжатие (Gzip/Brotli) и оптимизировать обработку соединений. Эта статья содержит практические советы по настройке Nginx и лучшие практики для значительного сокращения времени загрузки, улучшения пользовательского опыта и повышения общей скорости и эффективности вашего веб-сайта. Обязательное чтение для системных администраторов и веб-разработчиков, стремящихся к максимальной производительности.

Оптимизация производительности Nginx: советы для более быстрых сайтов

Медленные сайты обычно возникают из-за нескольких причин: дорогие ответы от вышестоящих серверов, отсутствие заголовков кэширования, слишком большие ресурсы, заблокированные рабочие процессы или сервер, настроенный на значения по умолчанию, а не под ваш трафик. Оптимизация производительности Nginx работает лучше всего, когда вы сначала измеряете, меняете одну настройку за раз и сохраняете конфигурацию читаемой.

Используйте приведенные ниже примеры в качестве отправных точек, затем тестируйте их под нагрузкой на своем приложении. Сервер статических файлов, сайт на WordPress/PHP-FPM и обратный прокси-сервер для API требуют разных компромиссов.

Понимание узких мест производительности Nginx

Начните с поиска узкого места. Распространенные причины включают:

  • Загрузка ЦП: Высокая загрузка ЦП замедляет обработку запросов, сжатие и работу TLS.
  • Нехватка памяти: Свопинг сильно увеличивает задержку.
  • Сетевой ввод-вывод: Медленные каналы, маленькие окна вышестоящих серверов или потеря пакетов могут доминировать во времени ответа.
  • Дисковый ввод-вывод: Статические файлы, файлы кэша и логи все равно обращаются к хранилищу.
  • Задержка вышестоящего сервера: Nginx может быть быстрым, в то время как ваш сервер приложений медленный.

Инструменты, такие как top, htop, iostat, ss, журналы доступа и модуль stub_status Nginx, могут помочь вам решить, что настраивать.

Основные методы оптимизации Nginx

Рабочие процессы и соединения

Директива worker_processes управляет тем, сколько рабочих процессов запускает Nginx. auto — это практическое значение по умолчанию, поскольку Nginx определяет доступные ядра ЦП.

# Установите worker_processes равным количеству ядер ЦП
worker_processes auto;

Внутри каждого рабочего процесса worker_connections ограничивает количество одновременных соединений, которые может открыть этот рабочий процесс. Примерная верхняя граница — worker_processes * worker_connections, но реальная емкость также зависит от соединений с вышестоящими серверами, лимитов открытых файлов, поведения keep-alive и ограничений операционной системы.

# Увеличьте worker_connections для сайтов с высоким трафиком
worker_connections 1024;

Если вы видите Too many open files, одного увеличения worker_connections недостаточно. Также проверьте лимит файловых дескрипторов службы, который часто контролируется LimitNOFILE в systemd или лимитами оболочки.

Стратегии кэширования

Кэширование обычно является наиболее эффективной оптимизацией производительности Nginx, поскольку предотвращает повторную работу.

Кэширование в браузере

Укажите браузерам кэшировать версионированные статические ресурсы, такие как изображения, CSS и JavaScript. Используйте длительное время жизни только когда имена файлов меняются при развертывании, например, app.8f3c1.css.

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

Прокси-кэширование

Если Nginx является обратным прокси, он может кэшировать выбранные ответы от бэкенда. Это хорошо работает для публичных страниц, ответов API с четкими правилами свежести и дорогих страниц, которые не меняются для каждого пользователя.

Сначала определите зону кэша в блоке http:

http {
    # ... другие конфигурации http ...
    proxy_cache_path /var/cache/nginx levels=1:2 keys_zone=my_cache:10m max_size=1g inactive=60m;
    # ...
}
  • /var/cache/nginx: Каталог, где будут храниться файлы кэша.
  • levels=1:2: Определяет структуру каталогов для кэша.
  • keys_zone=my_cache:10m: Создает зону разделяемой памяти с именем my_cache размером 10 МБ для хранения ключей кэша.
  • max_size=1g: Устанавливает максимальный размер кэша.
  • inactive=60m: Удаляет записи кэша, к которым не было обращений в течение 60 минут.

Затем включите кэширование в вашем блоке location:

location / {
    proxy_pass http://your_backend_app;
    proxy_cache my_cache;
    proxy_cache_valid 200 302 10m; # Кэшировать ответы 200 и 302 на 10 минут
    proxy_cache_valid 404 1m;     # Кэшировать ответы 404 на 1 минуту
    add_header X-Cache-Status $upstream_cache_status;
}

add_header X-Cache-Status $upstream_cache_status; полезен для отладки, показывая, был ли запрос попаданием в кэш, промахом или обходом.

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

Сжатие

Сжатие уменьшает размер передаваемых данных для текстовых ответов, таких как HTML, CSS, JavaScript, JSON и XML. Оно мало помогает для уже сжатых файлов, таких как JPEG, PNG, MP4 или многие архивные форматы.

http {
    # ...
    gzip on;
    gzip_vary on;
    gzip_proxied any;
    gzip_comp_level 6;
    gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;
    # ...
}
  • gzip on;: Включает сжатие Gzip.
  • gzip_vary on;: Добавляет заголовок Vary: Accept-Encoding, который важен для кэширующих прокси.
  • gzip_proxied any;: Сжимает ответы также для проксированных запросов.
  • gzip_comp_level 6;: Устанавливает уровень сжатия (1-9, выше — лучшее сжатие, но больше нагрузка на ЦП).
  • gzip_types ...;: Указывает MIME-типы для сжатия.

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

Обработка соединений и Keep-Alive

Директива keepalive_timeout управляет тем, как долго простаивающее клиентское соединение остается открытым. Повторное использование соединения позволяет избежать дополнительных рукопожатий TCP и TLS, но простаивающие соединения все равно потребляют ресурсы.

http {
    # ...
    keepalive_timeout 65;
    keepalive_requests 1000;
    # ...
}
  • keepalive_timeout 65;: Устанавливает тайм-аут keep-alive в 65 секунд.
  • keepalive_requests 1000;: Устанавливает максимальное количество запросов, которое может быть выполнено через одно keep-alive соединение.

Для API с множеством коротких запросов keep-alive помогает. Для небольшого сервера с множеством простаивающих клиентов может быть лучше более короткий тайм-аут.

Буферизация и лимиты размера запросов

Nginx использует буферы для тела клиентского запроса и проксированных ответов. Значения по умолчанию подходят для многих сайтов, но приложения с большим количеством загрузок и большие заголовки вышестоящих серверов могут потребовать явных настроек.

http {
    # ...
    client_body_buffer_size 10K;
    client_max_body_size 8M;
    proxy_buffers 8 16k;
    proxy_buffer_size 16k;
    proxy_connect_timeout 60;
    proxy_send_timeout 60;
    proxy_read_timeout 60;
    # ...
}
  • client_body_buffer_size: Размер буфера, используемого для чтения тела запроса клиента.
  • client_max_body_size: Максимально допустимый размер тела запроса клиента.
  • proxy_buffers, proxy_buffer_size: Управляют буферизацией, когда Nginx выступает в роли прокси.

Избегайте слепого копирования настроек буферов. Если вы видите upstream sent too big header, исследуйте заголовки вышестоящего сервера перед увеличением proxy_buffer_size. Если загрузки завершаются ошибкой 413 Request Entity Too Large, установите client_max_body_size в размер, который действительно поддерживает ваше приложение.

Оптимизация TLS

Для сайтов по HTTPS настройки TLS влияют как на задержку, так и на безопасность.

  • Возобновление сессий: Используйте кэш сессий для ускорения повторных соединений.
    ssl_session_cache shared:SSL:10m;
    ssl_session_timeout 10m;
    ssl_session_tickets off;
    
  • Версии TLS: Включайте TLS 1.2 и TLS 1.3, если ваши требования совместимости не говорят об обратном.
  • OCSP stapling: Может сократить количество циклов проверки сертификата, если ваша цепочка сертификатов это поддерживает.
    ssl_stapling on;
    ssl_stapling_verify on;
    resolver 8.8.8.8 8.8.4.4 valid=300s;
    

Обслуживание статических файлов

Nginx силен в обслуживании статических файлов. Эти директивы распространены в блоке http:

  • sendfile: Позволяет ядру копировать данные файла непосредственно в сокет на поддерживаемых системах.
    sendfile on;
    
  • tcp_nopush и tcp_nodelay: Настраивают поведение отправки пакетов для типичных HTTP-нагрузок.
    tcp_nopush on;
    tcp_nodelay on;
    

Мониторинг и тестирование

После каждого изменения тестируйте и сравнивайте. Полезные инструменты включают:

  • Nginx stub_status: Активные соединения, принятые соединения, обработанные соединения и запросы.
  • top/htop: Нагрузка на ЦП и память.
  • iostat: Дисковый ввод-вывод.
  • WebPageTest или PageSpeed Insights: Производительность на стороне браузера.
  • wrk, ab или hey: Локальное нагрузочное тестирование контролируемых конечных точек.

Сохраняйте копию предыдущей конфигурации, запустите sudo nginx -t, перезагрузите и сравните задержку, частоту ошибок, загрузку ЦП и время ответа вышестоящего сервера. Лучшая оптимизация производительности Nginx — та, которую могут подтвердить ваши измерения.

Практический вывод

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