Алгоритмы и методы распределения нагрузки на сервер

Обратный прокси-сервер — это служба, которая принимает запрос клиента, отправляет запрос одному или нескольким прокси-серверам, получает ответ и доставляет ответ сервера клиенту.

Требования

  • Не-root пользователь с доступом sudo
  • Предварительно установленный веб-сервер Nginx. Инструкции по установке стека LEMP в Ubuntu можно найти здесь.

Кроме того, для выполнения предложенных в руководстве примеров нужно иметь два доменных имени; в руководстве используются условные домены и . Не забудьте заменить их своими доменными именами.

Если у вас нет доменных имён, которые можно использовать для тестирования настроек, укажите фиктивные домены. В руководстве есть специальный раздел, объясняющий, как протестировать сайты при помощи локальной машины.

Балансировка нагрузки

Балансировка нагрузки предполагает, что у вебмастера есть в распоряжении несколько серверов (реальных или виртуальных), образующих кластер. Набор серверов, используемых для обслуживания одного сайта, также называют пулом. Метод балансировки позволяет распределять нагрузку между серверами из пула.

Как работает

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

Какие проблемы решает

Другое название этого комплекса мер — выравнивание нагрузки (load balancing). Эти методы повышают отказоустойчивость сайта, увеличивают его быстродействие, упрощают горизонтальное масштабирование кластера и позволяют делать резервные копии на нескольких серверах сразу.

Большая нагрузка на сервер хостинга может навредить и сайтам-соседям. Поэтому большинство хостеров предлагают готовые решения по определению и балансировке загруженности.

Контекст main

Укажем пользователя от имени которого будет работать сервер. При установке сервера был создан пользователь nginx, он и будет основным пользователем.

# Пользователь user nginx;

Определим число worker_processes или другими словами, рабочих процессов. Число процессов должно равняться числу процессорных ядер, хотя для последних версий nginx данный параметр рекомендуют устанавливать в значение auto. Поскольку на моем недорогом VPS/VDS сервере доступно одно ядро, то я устанавливаю значение равное единице.

# Количество рабочих процессов worker_processes 1;

Также зададим приоритет рабочих процессов, это нужно для того, чтобы при сильной нагрузке сервер сразу не упал мог продолжать обрабатывать запросы клиентов. Значения могут варьироваться от -20 до 20, причем чем больше будет отрицательное значение, тем больше будет приоритет процесса.

# Приоритет рабочих процессов worker_priority -5;

Указываем местонахождение pid-файла и лог-файла ошибок. Отмечаться будут только ошибки критического уровня, другими словами фиксация ошибок практически прекращается, в логах будут только события связанные со стартом или перезагрузкой сервера. Чем меньше производится записей в лог-файлы, тем меньше нагрузка на сервер.

Читайте также:  Обновление iOS 13.4 выпущено сегодня для всех

# Pid-файл и error_log файл сервера pid /var/run/; error_log /var/log/nginx/ crit;

NGINX vs Apache

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

Поскольку широкий функционал Nginx требует и значительно больших ресурсов системы, постоянно применять полноценную связку «Nginx + Apache» нецелесообразно.  Чаще оба веб-сервера используются в симбиозе — Nginx отдает статику и перенаправляет обработку скриптов Apache.

Нужно, чтобы Nginx и Apache работали без сбоев? Мощный VPS от Eternalhost позволит сохранить оптимальную производительность, даже при пиковых нагрузках.

NGINX vs Apache

Сильные и слабые стороны

  • Оба серверы хорошо работают на системах типа Unix, но производительность Nginx на Windows заметно ниже.
  • При одновременной работе Nginx оказывается в два раза быстрее Apache и использует меньше памяти. С динамическим контентом скорость равна.
  • Для получения пользовательской поддержки можно обратиться на форум или почту компании, но у Apache Foundation есть с этим проблемы.
  • Apache хорошо справляется с хостингом нескольких сайтов сразу, но Nginx показывает лучшую «гибкость» и эффективность работы с динамическим контентом.

Передача заголовков запроса

Когда Nginx проксирует запрос, он автоматически определяет два поля заголовка в проксируемых запросах от клиента, Host и Connection , и удаляет пустые заголовки. Host установлен на переменную $proxy_host , а Connection установлено на закрытие.

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

В следующем примере мы меняем значение поля заголовка Host на $host и удаляем поле заголовка Accept-Encoding , устанавливая его значение в пустую строку.

location / { proxy_set_header Host $host; proxy_set_header Accept-Encoding «»; proxy_pass http://localhost:3000; }

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

Серверные блоки

Независимо от источника установки файлы конфигурации будут содержать серверный блок (или блоки) для веб-сайта, обозначенный словом server. Например:

server { listen 80 default_server; listen [::]:80 default_server; server_name ; root /var/www/; index ; try_files $uri /; }

Директива server_name позволяет размещать несколько доменов на одном IP-адресе (виртуальные хосты). Выбор домена осуществляется на основании информации в заголовке полученного запроса.

Директива listen задает Nginx имя или IP-адрес узла и TCP-порт, который он должен прослушивать для HTTP-соединений. Аргумент default_server означает, что этот виртуальный хост будет отвечать на все запросы на порт 80, в которых в явном виде не будет указан другой виртуальный хост. Вторая такая директива устанавливает аналогичное поведение для IPv6-соединений.

Обычно для каждого домена или сайта на сервере требуется создать свой файл. Вот некоторые примеры:

запросов к и :

server_name ;

2.В директиве server_name можно использовать маски. Например, * и указывают серверу обрабатывать запросы на все поддомены :

server_name *; server_name ;

запросов ко всем доменным именам, начинающимся с example.:

server_name example.*;

Nginx разрешает указывать имена сервера, не соответствующие правилам доменных имен. Для ответа на запросы используется имя из заголовка HTTP вне зависимости от того, является ли оно допустимым доменным именем.

Это полезно, если ваш сервер работает в локальной сети или вы точно знаете все клиенты, которые будут осуществлять запросы, например, front-end прокси-серверы, у которых записи в /etc/hosts настроены на IP-адрес Nginx.

Мыши и слоны

Вопрос "Elephant vs Mice flows "стоит почти столько же, сколько существуют сети передачи данных. Одновременно с короткими TCP-сессиями открытия через сеть провайдера идут долгие тяжёлые закачки. Одновременно с HTTP-запросом на объект в Object Storage в сети ДЦ идёт массивная репликация БД. Но в сети провайдера по статистике количество одновременных сессий лежит в диапазоне от нескольких тысяч до десятков и сотен тысяч, среди которых большое количество и Mice, и Elephant flows. И это всё по ECMP может раскладываться сравнительно равномерно. В сети ДЦ ситуация радикально другая — количество сессий может быть и меньше тысячи, среди них буквально единицы-десятки Elephant flows. При статической балансировке велика вероятность, что массивные потоки лягут в один интерфейс и создадут очень неравномерную балансировку. Per-packet балансировка позволяет одинаково нагрузить все линки, но выливается в реордеринг. Как бы нам и один поток разложить в разные линки, и пакеты при этом доставлять упорядоченно? На помощь приходит статистика. Оказывается, что на маленьком масштабе времени TCP имеет взрывной характер — то есть, всплеск-пауза-всплеск-пауза-и т.д. Такие отдельные всплески внутри одного flow назвали flowlet.

И вот, если пауза между двумя соседними флоулетами больше определённого порога, то их можно безопасно отправить в разные линки, таким образом эффективно разложив один поток на несколько путей. Что же до длины паузы, то она должна быть больше, чем возможная разница во времени доставки пакетов по различным путям ECMP. Например, если эта разница лежит в диапазоне 300-500 мкс, то 1 мс паузы должно быть достаточно, чтобы исключить любой реордеринг.

Чем дальше в детали, тем ближе к чипо-вендорному разнообразию, но, если в общих словах, то реализуется это примерно так. Для того, чтобы отслеживать паузы, для каждого потока вводится элемент, называемый Hash Bucket Table. В каждой записи в нём есть поле с меткой времени, когда последний раз через него прогонялся пакет, и поле с некстхопом. При получении нового пакета, чип эту метку сравнивает с заданным временны́м порогом: если больше — то можно назначать новый интерфейс, если меньше, то слать в уже указанный в записи. По схожим принципам работает динамическая приоритизация пакетов (DPP — Dynamic Packet Prioritization). Но это уже совсем другая история.

Теперь мы готовы обратиться к слову "равноценный" во фразе "Что, по сути своей, такое ECMP? Это балансировка трафика по равноценным путям".

Основные ошибки nginx и их устранение

502 Bad Gateway

Ошибка означает, что NGINX не может получить ответ от одного из сервисов на сервере. Довольно часто эта ошибка появляется, когда NGINX работает в связке с Apache, Varnish, Memcached или иным сервисом, а также обрабатывает запросы PHP-FPM. Как правило, проблема возникает из-за отключенного сервиса (в этом случае нужно проверить состояние напарника и при необходимости перезапустить его) либо, если они находятся на разных серверах, проверить пинг между ними, так как, возможно, отсутствует связь между ними. Также, для PHP-FPM нужно проверить права доступа к сокету. Для этого убедитесь, что в /etc/php-fpm.d/ прописаны правильные права

Читайте также:  Как увеличить скорость модема Мегафон 4G?

listen = /tmp/ = www-data = www-data

504 Gateway Time-out

Ошибка означает, что nginx долгое время не может получить ответ от какого-то сервиса. Такое происходит, если Apache, с которым NGINX работает в связке, отдаёт ответ слишком медленно. Проблему можно устранить с помощью увеличения времени таймаута. При работе в связке NGINX+Apache в конфигурационный файл можно внести изменения:

server { … send_timeout 800; proxy_send_timeout 800; proxy_connect_timeout 800; proxy_read_timeout 800; … }

Тут мы выставили ожидание таймаута в 800 секунд.

Upstream timed out (110: Connection timed out) while reading response header from upstream

Причиной может быть сложная и потому долгая обработка php в работе PHP-FPM. Здесь тоже можно увеличить время ожидания таймаута

location ~ \.php$ { include fastcgi_params; fastcgi_index ; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; fastcgi_pass unix:/tmp/; fastcgi_read_timeout 800; }

800 секунд на ожидание ответа от бекенда.

Это лишь временные меры, так как при увеличении нагрузки на сайт ошибка снова станет появляться. Устраните узкие места, оптимизируйте работу скриптов php

413 Request Entity Too Large

Ошибка означает, что вы пытались загрузить слишком большой файл. В настройках nginx по умолчанию стоит ограничение в 1Mb. Для устранения ошибки в нужно найти строку

client_max_body_size 1m;

и заменить значение на нужное. Например, мы увеличим размер загружаемых файлов до 100Mb

client_max_body_size 100m;

Также, можно отключить проверку размера тела ответа полностью значением ноль:

client_max_body_size 0;

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

После каждого внесённого изменения в конфигурационный файл необходимо перезагружать nginx

304 Not Modified не устанавливается

Если возникает проблема с правильным отображением ответного заголовка сервера 304 Not Modified, то проблема, скорее всего, в пунктах:

  • В секции server конкретного сайта включен ssi on (Подробнее в документации). По умолчанию, ssi отключен, но некоторые хостеры и ISPManager любят его прописывать в дефолтную конфигурацию сайта включенным. Его нужно обязательно отключить, закомментировав или удалив эту строку;
  • if_modified_since установить в before, то есть на уровне http или конкретного server прописать: if_modified_since before;

Правильность ответа 304 Not Modified можно проверить с помощью:

  • Консоли разработчика браузера (F12) в разделе Network (Cеть) (не забываем перезагружать страницу);
  • Или сторонних сервисов, например

Client intended to send too large body

Решается с помощью увеличения параметра client_max_body_size

client_max_body_size 200m;