В предыдущей статье об обратном проксировании с помощью Nginx мы рассмотрели методику настройки сервера для перенаправления запросов к разным серверам. Развивая эту тему дальше, сегодня рассмотрим каким образом при помощи Nginx можно балансировать нагрузку между несколькими upstream-серверами, равномерно (или не очень) распределяя входящие запросы между ними.
Балансировка нагрузки может быть полезной в случаях, когда ваш один-единственный сервер уже не справляется с возложенными на него задачами в силу возросшего количества запросов. В Nginx роль балансировщика реализует модуль HttpUpstreamModule, обычно по умолчанию содержащийся в сборке Nginx. Тем, кто не читал предыдущих моих статей об Nginx и тем, что забыл, напоминаю о том, что все действия, описываемые в этой серии статей, тестировались и выполнялись на Debian 5 «Lenny» и в незначительной степени могут отличаться от требуемых в вашей системе.
Простая конфигурация
Допустим, вы разместили ваше приложение на нескольких серверах, пусть это будут три сервера с именами myserv-1.local, myserv-2.local и myserv-3.local, расположенные в вашей локальной сети (конечно же, на самом деле без разницы, где они будут размещаться). Для того, чтобы описать такое «облако» из трёх серверов в Nginx используется опция upstream:
upstream mySuperCloud { server myserv-1.local; server myserv-2.local; server myserv-3.local; }
Описанное таким образом «облако» из нескольких upstream-серверов теперь можно использовать в качестве значения параметра proxy_pass, рассмотренного в предыдущей статье. Везде, где Nginx будет наталкиваться на ссылку (в нашем случае — «mySuperCloud»), он будет по алгоритму Round-Robin выбирать следующий сервер и выполнять обратное проксирование к нему и от него. Таким образом, теперь, описывая виртуальный хост, вы можете сослаться на ваше «облако»:
server { listen 192.168.0.1:80; access_log /var/log/nginx/proxy.log; location / { proxy_pass http://mycloud; } }
Привязка клиента к серверу
Часто бывает нужно, чтобы один и тот же клиент, начав делать запросы к какому-то определённому серверу, не переключался на другие. Для этого в Nginx предусмотрена опция ip_hash. Если она определена, сервер будет запоминать IP-хеши клиентов и стараться проксировать каждого из них на один и тот же сервер.
upstream mySuperCloud { ip_hash; server myserv-1.local; server myserv-2.local; server myserv-3.local; }
Исключение сервера из «облака»
Если какой-то сервер по каким-то причинам вам необходимо отключить, чтобы Nginx не проксировал к нему клиентов, воспользуйетсь опцией down:
upstream mySuperCloud { server myserv-1.local; server myserv-2.local down; server myserv-3.local; }
Определение «веса» сервера
«Вес» сервера, грубо говоря, определяет насколько часто сервер будет использоваться. Например, вес сервера myserv-1.local равен 3, вес myserv-2.local равен 1 и вес myserv-3.local равен 2. В этом случае Nginx проксирует первых трёх клиентов к серверу myserv-1.local, четвёртого — к myserv-2.local, а пятого и шестого — к myserv-2.local, после чего круг начнётся сначала. Для определения веса сервера используется директива weight, значение по умолчанию которой равно единице.
upstream mySuperCloud { server myserv-1.local weight=3; server myserv-2.local; server myserv-3.local weight=2; }
Автоотключение серверов
Если какой-то из upstream-серверов перестанет отвечать на запросы, то подключение к нему станет невозможным. Nginx в этом случае переключиться на использование следующего сервера из «облака», однако каждый раз будет пытаться подключаться к неработающему серверу, растрачивая время. При помощи директивы max_fails параметра server можно определить максимально-допустимое количество неудачных попыток подключения к upstream-серверу, после чего тот будет считаться нерабочим и запросы к нему прекратятся. По умолчанию значение этого параметра равно единице, то есть после одной неудачной попытки Nginx на определённое время прекратит попытки новых подключений с нерабочему серверу. Это «определённое время» определяется значением опции fail_timeout, по умолчанию равным 10 секундам.
upstream mySuperCloud { server myserv-1.local max_fails=3 fail_timeout=120; server myserv-2.local; server myserv-3.local; }
Резервные серверы
Под понятием «резервный» в Nginx выступает сервер, который используется тогда, и только тогда, когда все «не резервные» upstream-серверы определены как нерабочие, т. е. не отвечающие на запросы. Резервные серверы отмечаются с помощью директивы backup:
upstream mySuperCloud { server myserv-1.local; server myserv-2.local; server myserv-3.local; server backup-server-1.local backup; server backup-server-2.local backup; }
А запилить подобное, тока если в вирт хостах прописать разные серверы с php-fpm на борту, и с смонтированой nfs www папкой?) Ну или что-то подобное, стоит оно того?)
Здравствуйте! Понимаю что опубликовано давно, однако же, есть надежда что кто-то сталкивался с подобной проблемой:
В своей работе для сохранения сессионности пользователей используем функцию ip_hash nginx.
Пример:
upstream backend {
ip_hash;
server 1.2.3.4:80 max_fails=3 fail_timeout=15s;
server 1.2.3.4:80 max_fails=3 fail_timeout=15s;
}
В аварийной ситуации столкнулись то ли с ошибкой, то ли с «фичей» реализации функции. Несмотря на то что бекенд-сервер указанный в директиве upstream по логам выведен из пула nginx при включенной ip_hash, продолжает отправлять на него запросы. Кто-нибудь может подсказать направление для дальнеших исследований? Так и должно быть?