Nginx, балансировка нагрузки с использованием алгоритмов липких и наименьших соединений одновременно
Мы используем Nginx в качестве балансировки нагрузки для нашего приложения websocket. Каждый сервер backend хранит информацию о сеансе, поэтому каждый запрос от клиента должен быть перенаправлен на тот же сервер. Поэтому для достижения этой цели мы используем директиву ip_hash
:
upstream app {
ip_hash;
server 1;
}
Проблема возникает, когда мы хотим добавить еще один сервер:
upstream app {
ip_hash;
server 1;
server 2;
}
Новые подключения идут на сервер 1 и сервер 2 - но это не то, что нам нужно в этой ситуации, так как загрузка на сервере 1 продолжает увеличиваться - нам все еще нужны липкие сеансы, но алгоритм least_conn
тоже включен, поэтому наши два сервера получают примерно равная нагрузка.
Мы также рассмотрели использование Nginx-sticky-module
, но в документе говорится, что если липкий файл cookie не будет доступен, он вернется к циклическому алгоритму Nginx по умолчанию, поэтому он также не решает проблему.
Итак, вопрос в том, можем ли мы объединить логику логики липких и наименьших соединений с помощью Nginx? Вы знаете, какие другие балансировки нагрузки решают эту проблему?
Ответы
Ответ 1
Возможно, использование модуля split_clients может помочь
upstream app {
ip_hash;
server 127.0.0.1:8001;
}
upstream app_new {
ip_hash;
server 127.0.0.1:8002;
}
split_clients "${remote_addr}AAA" $upstream_app {
50% app_new;
* app;
}
Это разделит ваш трафик и создаст переменную $upstreap_app
той, которую вы могли бы использовать, например:
server {
location /some/path/ {
proxy_pass http://$upstream_app;
}
Это временное решение для least_conn
и балансировки нагрузки, которые работают с липкими сеансами, "недостатком" является то, что, если нужно добавить больше серверов, необходимо создать новый поток, например:
split_clients "${remote_addr}AAA" $upstream_app {
30% app_another_server;
30% app_new;
* app;
}
Для тестирования:
for x in {1..10}; do \
curl "0:8080?token=$(LC_ALL=C; cat /dev/urandom | tr -dc 'a-zA-Z0-9' | fold -w 32 | head -n 1)"; done
Более подробную информацию об этом модуле можно найти в этой статье (Выполнение тестирования A/B)
Ответ 2
Вы можете легко достичь этого, используя HAProxy, и я действительно предлагаю перейти чтобы узнать, как ваша текущая настройка может принести пользу.
С HA Proxy у вас будет что-то вроде:
backend nodes
# Other options above omitted for brevity
cookie SRV_ID prefix
server web01 127.0.0.1:9000 cookie check
server web02 127.0.0.1:9001 cookie check
server web03 127.0.0.1:9002 cookie check
Это просто означает, что прокси-сервер отслеживает запросы на серверы с помощью куки файлов.
Однако, если вы не хотите использовать HAProxy, я бы посоветовал вам настроить изменение вашей реализации сеанса для использования в памяти DB, например redis/memcached. Таким образом, вы можете использовать lessconn или любой другой алгоритм, не беспокоясь о сеансах.