Как стать автором
Обновить

Комментарии 22

Подскажите состояние сессии пользователя при его повторных запросах будет идти к серверу, который был выбран балансировщиком при первом запросе?

Спасибо

Спасибо за статью!

Правильно ли я понимаю, что единой точкой отказа может быть сервер балансировки, на котором работает nginx? Как лучше обеспечить защиту от отказа этого сервера?

И еще вопрос - как балансировщик на базе nginx будет поступать с отказавшими узлами бэкэнда? Он их автоматически исключит из процесса балансировки?

Можно сделать несколько балансировщиков и ротировать их уже через DNS roundrobin.

Что бы DNS не стал бы единой точкой отказа можно использовать какого-либо провайдера, умеющего в anycast DNS.

Может знаете, что делать в такой ситуации.

Есть локальный DNS-сервер (bind9 на Debian) с двумя A-записями, в которых два разных IP-адреса (разные подсети) ссылаются на один и тот же DNS-адрес. В идеальных условиях, с использованием roundrobin, на запрос по DNS-имени откликается один из двух веб-серверов с вероятностью 50/50. Но если один из серверов падает, то клиент через DNS-сервер может ещё долго стучаться на дохлый IP, пока не будет автоматически перенаправлен на рабочий сервер.

Какими готовыми методами можно уменьшить время отклика до 5-10 секунд? На ум приходит разве что идея с написанием скрипта, проверяющего состояние веб-серверов и перезаписывающего А-записи в случае отсутствия отклика на запросы. Пробовал также keepalived, но как я понял, он идеально работает только с IP-адресами в одной подсети и не умеет спрашивать хосты по DNS-записям.

Если речь идет о том, что у вас два сервера являются зеркалами одного и того же сайта, то можно просто поставить всё под CloudFlare а там уже настроить два сервера, между которыми сам CloudFlare будет 50/50 раскидывать запросы. Фиксацию сессии CloudFlare в таком случае не делает. Управлять этим примитивным балансировщиком можно через API, оно там простое. Мониторить можно своим скриптом или с помощью Zabbix, у CloudFlare есть какая-то интеграция с Zabbix и он вроде бы должен видеть показатели по отдельным серверам (количество запросов, количество ответов/неответов и так далее). То есть должно в теории получить так, что Cloud Flare и предоставляет DNS, и проксирует трафик на два сервера, и выдает статистику, и принимает команды на исключение одного из этих серверов.

При такой схеме балансировки конечный клиент (браузер) всегда работает с одним и тем же сервером и IP этого сервера для него никогда не меняется.

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

Если не хочется использовать CloudFlare или другие подобные системы тогда остается только собирать мониторинг и управление самостоятельно. Тогда да, это будет либо собственный скрипт, либо каке-то настройки Zabbix.

Правильно ли я понимаю, что единой точкой отказа может быть сервер
балансировки, на котором работает nginx? Как лучше обеспечить защиту от
отказа этого сервера?

Да. Есть вот такой простенький вариант как раз для такого случая: https://habr.com/ru/post/683770/

И еще вопрос - как балансировщик на базе nginx будет поступать с
отказавшими узлами бэкэнда? Он их автоматически исключит из процесса
балансировки?

Да: http://nginx.org/en/docs/http/load_balancing.html#nginx_load_balancing_health_checks. Впрочем, об этом и в статье написано.

НЛО прилетело и опубликовало эту надпись здесь

Поддерживаю, а заодно бы и рассмотреть к примеру кластер из nginx'ов и их "готовку" вместе (хотелось бы посмотреть на практики и сравнить с тем, что сам городил).

Nginx справляется с балансировкой только до тех пор, пока все рилы живы или, хотя бы, быстро отвечают RST.

И вообще не справляется, если одна из посещаемых ручек апстрима всегда возвращает ошибку.

почему это?
http://nginx.org/en/docs/http/ngx_http_upstream_module.html#max_fails
What is considered an unsuccessful attempt is defined by the proxy_next_upstream, fastcgi_next_upstream, uwsgi_next_upstream, scgi_next_upstream, memcached_next_upstream, and grpc_next_upstream directives.


вариативность не очень велика, но для 50x, например, можно настроить, чтобы их получение считалось признаком проблем у апстрима

Без healthcheck всё это работает плохо.

обоснуйте.
апстрим начал выдавать ошибки — нагрузка с него перешла на другие апстримы.


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

Вкратце - без healtcheck рилы либо будут постоянно флапать в up/down на запросах пользователей, либо каждый Х-ный запрос будет лагать, попадая на упавший рил (до срабатывания next_upstream), либо слягут вообще все бэкэнды из-за одной ручки - в зависимости от того, как настроено.

Хорошего решения без асинхронных с запросами от пользователей healthcheck и отстрела рилов вообще пока не придумали.

Нельзя рил проверять синхронно с запросом пользователей - они это видят. Лучше 3 секунды до следующего healtcheck отдавать 500-ку (хотя тот же haproxy помимо healthcheck и next_upstream может сделать), чем пытаться лить настоящие запросы в умерший риал-сервер и на основе этого включать-выключать рилы.

ЗЫ - много кто использует nginx как балансер из крупняка, но у них написаны свои плагины для healthcheck.

ну вот смотрите, апстрим работал нормально и стал выдавать ошибки, nginx увидит это сразу и сможет отключить его.
healtcheck же увидит падение с какой-то задержкой, нет?

А теперь давайте поиграем в упражнение - угадайте, как и когда nginx будет рил подключать обратно?

А теперь представьте, что рил не мнгновенно отвечает пятисоткой, а вообще ничего не отвечает и коннект к нему уходит в tcp timeout из-за blackhole. Ну да, можно выставить таймауты в настройках upstream/proxy_pass - но тогда одна медленная ручка положит все рилы.

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

В детальной статье, в которой показано как установить и настроить NGINX ни слова не говорится о том в какой момент такая балансировка вообще становится актуальна. Что лучше балансировка в среде из 3 серверов по 1 ядру и 500 мб оперативки или прямой доступ на сервер с 3 ядрами и 1.5 Гб оперативки. Или балансировщик в среде с 1 сервером распределяющий запросы по изолированным виртуальным машинам и в каких случаях это вообще становится нужно. ( Может быть увеличить параметры виртуальной машины будет более правильным шагом ?) Ведь сам по себе NGINX уже балансирует запросы по набору запущенных в операционной системе процессов...

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

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

Спасибо.

Попробую ответить на ваш вопрос, пусть может быть и не полностью...

Для чего балансировать? Ну тут очевидно, чтобы равномерно распределить нагрузку. Например, есть у нас за nginx N php-fpm инстансов (у которых конечное количество воркеров, не будем углубляться в правильный рассчет их кол-ва, но пусть будет X), и тогда параллельно сервис сможет обработать N*X запросов, при этом каждый инстанс будет обрабатывать только свою часть. И тут как раз нюанс на тему, что лучше, один жирный инстанс, или несколько, но поменьше. Всё зависит от задач которые они выполняют. Где-то можно и одним обойтись, а где-то лучше очень много но слабеньких. Например, если на каком-нибудь VPS провайдере у вас будет лимит на входящий канал, а сервис должен по запросу что-то выкачивать, и не всегда может быть такое, что в более жирной VM дадут канал более широкий, вполне может быть что везде он будет по 10Mbit. Да, пример абстрактный, но лишь пример. Так же можно еще учесть что более жирному инстансу придется ворочать большим количеством процессов, а это лишние переключения контекста и т.д.

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

Какие дополнительные плюшки от использования upstream? Самая главная вещь, это то, что в случае падения какого-то бэкенда -- сервис продолжит работать, просто запросы перетекут на остальные живые. А почему он может упасть -- причин может быть сотня. От простого kernel panic, развалившейся файловой системы или просто от того что место на диске закончилось, заканчивая тем, что без лишних телодвижений его можно будет планово самому потушить например для того, чтобы произвести обновление ПО, перезагрузить и т.п.

По идее nginx reload лучше nginx restart в случае, когда вы просто изменили конфиг.

>Разница между прямым и обратным прокси заключается в том, что прямой прокси находится перед несколькими клиентами, а обратный прокси — перед несколькими бэкендами.

Обратный прокси-сервер может спокойно находиться и перед одним "бэкэндом".

Также мне не нравится этот пассаж:

>Они оба могут использоваться для повышения производительности и доступности веб-сайта или приложения, а также для распределения трафика между несколькими серверами

Я только пытаюсь разобраться в теме, и такие утверждения создают путаницу. Реверс-прокси разве может обслуживать несколько серверов? В таком случае он уже является балансировщиком нагрузки. Это же просто задача - балансировка, реверс-проксирование. Распределяешь трафик по нескольких веб-серверам - всё, ты уже балансировщик. И как реверс-прокси может повышать доступность, если он один сервер обслуживает? А еще при добавлении веб-сервера единая точка отказа переносится с него на сам реверс-прокси или балансировщик. Само по себе это не увеличивает доступность (без добавления второго прокси).

Зарегистрируйтесь на Хабре, чтобы оставить комментарий