sticky session что это
Sticky and NON-Sticky sessions
I want to know the difference between sticky- and non-sticky sessions. What I understood after reading from internet:
Sticky : only single session object will be there.
Non-sticky session : session object for each server node
2 Answers 2
When your website is served by only one web server, for each client-server pair, a session object is created and remains in the memory of the web server. All the requests from the client go to this web server and update this session object. If some data needs to be stored in the session object over the period of interaction, it is stored in this session object and stays there as long as the session exists.
However, if your website is served by multiple web servers which sit behind a load balancer, the load balancer decides which actual (physical) web-server should each request go to. For example, if there are 3 web servers A, B and C behind the load balancer, it is possible that www.mywebsite.com is served from server A, www.mywebsite.com is served from server B and www.mywebsite.com/ are served from server C.
If the load balancer is instructed to use sticky sessions, all of your interactions will happen with the same physical server, even though other servers are present. Thus, your session object will be the same throughout your entire interaction with this website.
To summarize, In case of Sticky Sessions, all your requests will be directed to the same physical web server while in case of a non-sticky load balancer may choose any webserver to serve your requests.
As an example, you may read about Amazon’s Elastic Load Balancer and sticky sessions here : http://aws.typepad.com/aws/2010/04/new-elastic-load-balancing-feature-sticky-sessions.html
I’ve made an answer with some more details here : https://stackoverflow.com/a/11045462/592477
Or you can read it there ==>
When you use loadbalancing it means you have several instances of tomcat and you need to divide loads.
Привязка сессии к серверу в Nginx. Nginx-sticky-module
Sticky session — метод балансировки нагрузки, при котором запросы клиента передаются на один и тот же сервер группы.
Самый простой способ закрепить сессии пользователя за конкретным сервером в Nginx — использовать метод ip-hash:
При использовании этого метода запросы распределяются по серверам на основе IP-адресов клиента. В качестве ключа для хэширования используются первые три октета IPv4-адреса клиента или IPv6-адрес клиента целиком. Метод гарантирует, что запросы одного и того же клиента будут всегда передаваться на один и тот же сервер. Если же этот сервер будет считаться недоступным, то запросы этого клиента будут передаваться на другой сервер(с). Из метода балансировки следуют его минусы: проблемы поддержки сессии при использовании клиентом динамического IP; не равновесная балансировка, если большое количество запросов, например, проходит через один прокси сервер. Использование cookie решает эти проблемы.
В Nginx существует метод sticky использующий cookie для балансировки, правда только в коммерческой версии. Есть и более бесплатный путь — использование внешних модулей.
Nginx-sticky-module
Модуль создает cookie — чем делает каждый браузер уникальным — и далее использует его для переадресации запросов на один и тот же сервер. При отсутствии cookie, например при первом запросе, сервер выбирается случайным образом. Проект был разветвлен, оригинальная версия больше не поддерживается, поддерживаемое ответвление называется nginx-sticky-module-ng и находится здесь. Обе ссылки приведены т.к. при google запросе «sticky session nginx» первой в списке, после ссылок на официальный сайт nginx, оказывается ссылка именно на оригинальный сайт проекта. И если вы, как и я, не обратили внимание на едва заметный подзаголовок, написанный заглавными буквами и жирным шрифтом: DEPRECATED и ниже на ссылку на поддерживаемую версию — перед инсталляцией модуля потребуется внести в исходный код некоторые изменения. Дело в том, что начиная с версии nginx 1.5.8 поменялся API для nginx метода ngx_sock_ntop(), поэтому в файле ngx_http_sticky_misc.c архива nginx-sticky-module строку
Чтобы установить этот модуль, нужно скомпилировать Nginx с этим модулем. Для этого нужно, если нет, установить компилятор С/С++ и библиотеки, используемые nginx (для RedHat/CentOS):
скачать последнюю версию исходников Nginx, распаковать ее в не труднодоступное место, найти в распакованном папку src, распаковать в нее архив nginx-sticky-module или nginx-sticky-module-ng и далее определившись с опциями nginx, которые будут нужны, скомпилировать
init.d script можно найти здесь, который нужно скопировать в файл:
и дать ему права запуска
после чего можно использовать команды сервиса и настроить автоматический запуск после перезагрузки:
Настройка sticky session выглядит не сложнее, чем для метода ip_hash:
По умолчанию будет создаваться cookie с именем route и временем жизни 1 час. Метод может принимать несколько аргументах, о которых можно узнать на сайтах модулей.
Для любителей извращений и обходиться без сторонних модулей можно использовать настройку sticky session представленную здесь.
Липкие и не липкие сессии
Я хочу знать разницу между липкими и нелипкими сессиями. Что я понял после прочтения из интернета:
Важно : только один объект сеанса будет там.
Non-sticky session : объект сеанса для каждого узла сервера
Когда ваш веб-сайт обслуживается только одним веб-сервером, для каждой пары клиент-сервер создается объект сеанса, который остается в памяти веб-сервера. Все запросы от клиента отправляются на этот веб-сервер и обновляют этот объект сеанса. Если некоторые данные необходимо хранить в объекте сеанса в течение периода взаимодействия, они сохраняются в этом объекте сеанса и остаются там до тех пор, пока существует сеанс.
Если подсистеме балансировки нагрузки предписано использовать липкие сеансы, все ваши взаимодействия будут происходить с одним и тем же физическим сервером, даже если присутствуют другие серверы. Таким образом, ваш объект сеанса будет одинаковым на протяжении всего вашего взаимодействия с этим сайтом.
Подводя итог, можно сказать, что в случае Sticky Sessions все ваши запросы будут направлены на один и тот же физический веб-сервер, а в случае несвязанного loadbalancer может выбрать любой веб-сервер для обслуживания ваших запросов.
В качестве примера вы можете прочитать об Amazon Elastic Load Balancer и липких сессиях здесь: http://aws.typepad.com/aws/2010/04/new-elastic-load-balancing-feature-sticky-sessions.html
Я сделал ответ с более подробной информацией здесь: https://stackoverflow.com/a/11045462/592477
Или вы можете прочитать это там ==>
Когда вы используете балансировку нагрузки, это означает, что у вас есть несколько экземпляров tomcat, и вам нужно разделить нагрузки.
Балансировка нагрузки с помощью NGINX
В данной инструкции мы рассмотрим процесс настройки балансировки, в основном, http-запросов с помощью веб-сервера NGINX. По большей части, инструкция подойдет для любого дистрибутива Linux, и даже, Windows (за исключением путей расположения конфигурационных файлов). Таким образом настроенный NGINX сможет обеспечить распределение нагрузки и отказоустойчивость нашим сетевым сервисам.
Обратите внимание, что NGINX умеет распределять не только http-запросы. Его можно использовать для балансировки запросов на 4-м уровне модели OSI (TCP и UDP), например, подключения к СУБД, DNS и так далее — по сути, любой сетевой запрос может быть обработан и распределен с помощью данного программного продукта.
Постепенно рассмотрим разные варианты настройки распределения нагрузки в NGINX. Начнем с простого понимания, как работает данная функция и закончим некоторыми примерами настройки балансировки.
Основы
Чтобы наш сервер мог распределять нагрузку, создадим группу веб-серверов, на которые будут переводиться запросы:
* в данном примере мы создаем файл upstreams.conf, в котором можем хранить все наши апстримы. NGINX автоматически читает все конфигурационные файлы в каталоге conf.d.
upstream dmosk_backend <
server 192.168.10.10;
server 192.168.10.11;
server 192.168.10.12;
>
* предполагается, что в нашей внутренней сети есть кластер из трех веб-серверов — 192.168.10.10, 192.168.10.11 и 192.168.10.12. Мы создали апстрим с названием dmosk_backend. Позже, мы настроим веб-сервер, чтобы он умел обращаться к данному бэкенду.
В настройках сайта (виртуального домена) нам необходимо теперь проксировать запросы на созданный upstream. Данная настройка будет такой:
server <
.
location / <
proxy_pass http://dmosk_backend;
>
.
>
* данная настройка для нашего сайта укажет, что все запросы мы должны переводить на апстрим dmosk_backend (который, в свою очередь, будет отправлять запросы на три сервера).
Проверяем корректность нашего конфигурационного файла:
Если ошибок нет, перезапускаем сервис:
systemctl restart nginx
Приоритеты
При настройке бэкендов мы можем указать, кому наш веб-сервер будет отдавать больше предпочтение, а кому меньше.
Синтаксис при указании веса:
По умолчанию приоритет равен 1.
Также мы можем указать опции:
Давайте немного преобразуем нашу настройку upstreams:
upstream dmosk_backend <
server 192.168.10.10 weight=100 ;
server 192.168.10.11 weight=10 ;
server 192.168.10.12;
server 192.168.10.13 backup ;
>
* итак, мы указали нашему серверу:
Задержки, лимиты и таймауты
По умолчанию, NGINX будет считать сервер недоступным после 1-й неудачной попытки отправить на него запрос и в течение 10 секунд не будут продолжаться попытки работы с ним. Также каждый сервер не имеет ограничений по количеству к нему подключений.
Изменить поведение лимитов и ограничений при балансировке можно с помощью опций:
server max_fails= fail_timeout= ;
В нашем примере мы преобразуем настройку так:
upstream dmosk_backend <
server 192.168.10.10 weight=100 max_conns=1000 ;
server 192.168.10.11 weight=10 max_fails=2 fail_timeout=90s ;
server 192.168.10.12 max_fails=3 fail_timeout=2m ;
server 192.168.10.13 backup;
>
Метод балансировки
Рассмотрим способы балансировки, которые можно использовать в NGINX:
Настройка метода балансировки выполняется в директиве upstream. Синтаксис:
Round Robin
Веб-сервер будет передавать запросы бэкендам по очереди с учетом их весов. Данный метод является методом по умолчанию и его указывать в конфигурационном файле не нужно.
Данный метод определяет контрольную сумму на основе переменных веб-сервера и ассоциирует каждый полученный результат с конкретным бэкендом. Пример настройки:
* это самый распространенный пример настройки hash — с использованием переменных $scheme (http или https) и $request_uri. При данной настройке каждый конкретный URL будет ассоциирован с конкретным сервером.
IP Hash
Ассоциация выполняется исходя из IP-адреса клиента и только для HTTP-запросов. Таким образом, для каждого посетителя устанавливается связь с одним и тем же сервером. Это, так называемый, Sticky Session метод.
Для адресов IPv4 учитываются только первые 3 октета — это позволяет поддерживать одинаковые соединения с клиентами, чьи адреса меняются (получение динамических адресов от DHCP провайдера). Для адресов IPv6 учитывается адрес целиком.
upstream dmosk_backend <
ip_hash;
server 192.168.10.10;
server 192.168.10.11;
server 192.168.10.12;
>
Least Connections
NGINX определяет, с каким бэкендом меньше всего соединений в данный момент и перенаправляет запрос на него (с учетом весов).
Настройка выполняется с помощью опции least_conn:
upstream dmosk_backend <
least_conn;
server 192.168.10.10;
server 192.168.10.11;
server 192.168.10.12;
>
Random
Запросы передаются случайным образом (но с учетом весов). Дополнительно можно указать опцию two — если она задана, то NGINX сначала выберет 2 сервера случайным образом, затем на основе дополнительных параметров отдаст предпочтение одному из них. Это следующие параметры:
upstream dmosk_backend <
random two least_conn;
server 192.168.10.10;
server 192.168.10.11;
server 192.168.10.12;
>
Least Time
Данная опция будет работать только в NGINX Plus. Балансировка выполняется исходя из времени ответа сервера. Предпочтение отдается тому, кто отвечает быстрее.
Опция для указания данного метода — least_time. Также необходимо указать, что мы считаем ответом — получение заголовка (header) или когда страница возвращается целиком (last_byte).
upstream dmosk_backend <
least_time header;
server 192.168.10.10;
server 192.168.10.11;
server 192.168.10.12;
>
* в данном примере мы будем делать расчет исходя из того, как быстро мы получаем в ответ заголовки.
upstream dmosk_backend <
least_time last_byte;
server 192.168.10.10;
server 192.168.10.11;
server 192.168.10.12;
>
* в данном примере мы будем делать расчет исходя из того, как быстро мы получаем в ответ целую страницу.
Сценарии настройки
В реальной жизни настройки могут быть несколько сложнее, чем приведенные здесь или в официальной документации. Рассмотрим несколько примеров, что может понадобиться настроить при балансировке.
1. Backend на https
Предположим, что наши внутренние серверы отвечают по SSL-каналу. Таким образом, нам нужно отправлять запрос по порту 443. Также схема проксирования должна быть https.
Настройка сайта:
* обратите внимание на 2 момента:
Настройка upstream:
upstream dmosk_backend <
server 192.168.10.10:443;
server 192.168.10.11:443;
server 192.168.10.12:443;
>
* в данном примере мы указали конкретный порт, по которому должно выполняться соединение с бэкендом. Для упрощения конфига дополнительные опции упущены.
2. Разные бэкенды для разных страниц
Нам может понадобиться разные страницы сайта переводить на разные группы внутренних серверов.
Настройка сайта:
server <
.
location /page1 <
proxy_pass http://backend1;
>
location /page2 <
proxy_pass http://backend2;
>
.
>
* при такой настройке мы будем передавать запросы к странице page1 на группу backend1, а к page2 — backend2.
Настройка upstream:
upstream backend1 <
server 192.168.10.10;
server 192.168.10.11;
>
upstream backend2 <
server 192.168.10.12;
server 192.168.10.13;
>
* в данном примере у нас есть 2 апстрима, каждый со своим набором серверов.
3. На другой хост
Может быть необходимым делать обращение к внутреннему ресурсу по другому hostname, нежели чем будет обращение к внешнему. Для этого в заголовках проксирования мы должны указать опцию Host.
Настройка сайта:
* в данном примере мы будем проксировать запросы на бэкенды, передавая им имя хоста internal.domain.com.
4. TCP-запрос
Рассмотрим, в качестве исключения, TCP-запрос на порт 5432 — подключение к базе PostgreSQL.
Настройка сайта:
server <
listen 5432;
proxy_pass tcp_postgresql;
>
* в данном примере мы слушаем TCP-порт 5432 и проксируем все запросы на апстрим tcp_postgresql.
Настройка upstream:
upstream tcp_postgresql <
server 192.168.10.14:5432;
server 192.168.10.15:5432;
>
* запросы будут случайным образом передаваться на серверы 192.168.10.14 и 192.168.10.15.
5. UDP-запрос
Рассмотрим также и возможность балансировки UDP-запросов — подключение к DNS по порту 53.
Настройка сайта:
server <
listen 53 udp;
proxy_pass udp_dns;
proxy_responses 1;
>
* в данном примере мы слушаем UDP-порт 53 и проксируем все запросы на апстрим udp_dns. Опция proxy_responses говорит о том, что на один запрос нужно давать один ответ.
Настройка upstream:
upstream udp_dns <
server 192.168.10.16:53;
server 192.168.10.17:53;
>
* запросы будут случайным образом передаваться на серверы 192.168.10.16 и 192.168.10.17.
Читайте также
Возможно, данные инструкции также будут полезны:
Липкие сессии для самых маленьких [Часть 1]
Липкие сессии (Sticky-session) — это особый вид балансировки нагрузки, при которой трафик поступает на один определенный сервер группы. Как правило, перед группой серверов находится балансировщик нагрузки (Nginx, HAProxy), который и устанавливает правила распределения трафика между доступными серверами.
В первой части цикла мы посмотрим как создавать липкие сессии с помощью Nginx. Во второй же части разберем создание подобной балансировки средствами Kubernetes.
Перед тем как настроить nginx, сделаем простенький сервис на фреймворке FastAPI для наглядной демонстрации распределения трафика. Создадим проект с виртуальным окружением Python 3.6+. В директории проекта должны находится следующие файлы:
Файл requirements.txt содержит несколько зависимостей:
main.py содержит следующий код:
Обратите внимание на переменную uuid, которая инициализируется вместе с FastAPI приложением. Переменная будет жить, пока работает сервер. Собственно, по значению этой переменной мы будем точно знать, что попали на тот же самый экземпляр приложения. Перед тем как запустить сервис нужно установить зависимости:
Запустить сервис можно командой:
Проверим работу сервиса с помощью Postman, указываем 0.0.0.0:8080 и нажимаем Send. Сервер ответит сгенерированным uuid:
Рассмотрим содержание Dockerfile. Предполагается, что у вас есть хотя бы небольшой опыт работы с контейнерами.
Это очень похоже на то, что мы сделали вручную: создали окружение, установили зависимости, запустили проект. Ну, разве что порт не публиковали.
Соберём образ (не забываем про точку):
И запустим контейнер с пробросом портов:
Пощелкайте Postman убедитесь, что все также работает. Теперь сделаем запуск приложения в несколько реплик.
В корне директории проекта создадим файлик docker-compose.yaml. Вставим следующий код:
Данная инструкция запустит в docker-compose приложение web. В build указывается место расположения образа (в нашем случае Dockerfile лежит в корне директории) на основе которого собирается контейнер. В ports открываем порты 8080 и 8081 которые будут связаны с портом 8080 внутри контейнера. Запись в виде диапазона нужна при запуске приложения в несколько инстансов (реплик). Приложения сами займут свободные порты из предоставленного пула. Только единственное условие: количество портов в пуле должно быть больше либо равно количеству запускаемых реплик, иначе возникнет ошибка.
Запустить несколько контейнеров разом можно командой:
В Postman проверим работу контейнеров 0.0.0.0:8080 и 0.0.0.0:8081 – отвечают оба сервера:
Теперь можно приступить к настройке Nginx!
Создадим папку nginx, а в нем файлик nginx.conf.
Внутри nginx.conf опишем следующее:
Данный конфиг указывает nginx слушать порт 80 и весь трафик проксировать на сервера перечисленные в upstream. В данной конфигурации происходит балансировка типа round-robin, липкие сессии добавим попозже.
Теперь поднимем nginx вместе с приложением web. В docker-compose-yaml добавим следующее:
Тут все просто. В image указывается какой официальный образ забрать при сборке. В Volumes мы монтируем наш конфиг из рабочей директории прямиком в контейнер. Это например, позволит нам изменять конфиг nginx и не пересобирать заново docker-compose, достаточно будет только перезапустить nginx контейнер.
Финальный штрих: подключим приложение web и nginx к новой сети app-net. Благодаря этому в конфиге nginx можно указывать DNS сервиса (web), который определен в docker-compose.
Полный docker-compose.yaml выглядит так:
Удалим запущенные контейнеры:
И запустим сервис в двух экземплярах вместе с nginx:
В Postman отправляем запросы на порт 80 и видим, что балансировка работает – ответы приходят разные.
Теперь сделаем наконец липкие сессии! Обновим конфиг nginx добавив одну строчку в блок upstream:
Полный конфиг nginx
альтернатива для директивы hash
Помимо директивы hash, существует также ip_hash. В этом случае nginx будет перенаправлять трафик в зависимости от ip-адреса клиента.
После сборки создадим в Postman cookie c именем key для адреса 0.0.0.0 :
И отправим запрос по тому же адресу:
Ответ изменился и больше не меняется с отправкой новых запросов. Готово! Таким простым способом можно реализовать липкие сессии в nginx.
Подобная балансировка имеет большой минус: трафик может быть сконцентрирован на конкретном приложении, пока остальные недостаточно нагружены или еще хуже вообще простаивают.
В NGINX PLUS (платная версия) реализованы продвинутые липкие сессии. Где можно указать таймаут по истечении которого трафик прилипнет к другому серверу из группы. Это более сбалансированные липкие сессии.
Что делать если не хочется платить? Можно разрулить это на стороне самого приложения и подставлять в cookie другое значение key спустя некоторое время. Но надо учитывать, что в таком случае нарушается принцип единой ответственности. Сервис не должен знать или уметь себя балансировать, это уже заботы вышестоящей инстанции.
В следующей части разберем создание липкой сессии в kubernetes.