Sticky Sessions с Apache APISIX - Теория

Nicolas Fränkel

Nicolas Fränkel

July 27, 2023

Technology

Постоянные сессии, также известные как привязка сессий, — это механизм, при котором компонент маршрутизации, выступающий в роли фасада, всегда направляет запрос на один и тот же вышестоящий узел. В этой статье я расскажу о причинах использования постоянных сессий, доступных альтернативах и о том, как их реализовать с помощью Apache APISIX.

Зачем нужны постоянные сессии?

Постоянные сессии стали популярными, когда состояние хранилось на вышестоящем узле, а не в базе данных. Я использую пример упрощенного интернет-магазина, чтобы объяснить это подробнее.

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

Базовая архитектура интернет-магазина

Если бизнес успешен, он будет расти, и в какой-то момент вам потребуется масштабировать эту архитектуру. Когда вертикальное масштабирование (увеличение мощности машин) становится невозможным, необходимо масштабировать горизонтально (добавлять больше узлов). С добавлением узлов веб-приложения вам также понадобится механизм балансировки нагрузки перед узлами веб-приложения, чтобы распределять нагрузку между ними.

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

Обращение к базе данных каждый раз — это дорогостоящая операция. Это допустимо для данных, которые используются редко. Однако мы хотим отображать содержимое корзины для каждого запроса. Доступно несколько альтернатив для ускорения этого процесса. Если мы предполагаем, что веб-приложение использует серверный рендеринг, классическим решением будет хранение данных, связанных с корзиной, в памяти на узле веб-приложения.

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

Ограничения постоянных сессий

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

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

Хотя репликация сессий существует во всех технологических стеках, нет единой спецификации на этот счет. Я знаком с JVM, поэтому вот несколько вариантов:

  • Tomcat предлагает репликацию сессий из коробки
  • Hazelcast предлагает кластерное решение для хранения данных в памяти, которое можно интегрировать на разных уровнях
  • Spring Session — это уровень абстракции над конкретными решениями

Когда данные реплицируются на всех узлах (или в удаленном кластере), можно подумать, что постоянные сессии больше не нужны. Это верно, если учитывать только доступность, но не производительность. Речь идет о локальности данных: получение данных на текущем узле быстрее, чем из другого места через сеть.

Постоянные сессии в Apache APISIX

Постоянные сессии — это обязательная функция для любого балансировщика нагрузки, обратного прокси и API-шлюза, которые стоят своего названия. Однако я должен признать, что документация Apache APISIX нуждается в более простом введении в эту тему.

Apache APISIX связывает маршрут с вышестоящим узлом. Вышестоящий узел состоит из одного или нескольких узлов. Когда запрос соответствует маршруту, Apache APISIX должен выбрать среди всех доступных узлов, на который направить запрос. По умолчанию используется алгоритм взвешенного циклического перебора (round-robin). Циклический перебор использует узлы по очереди, а после последнего возвращается к первому. При взвешенном циклическом переборе вес влияет на то, сколько запросов Apache APISIX направляет на узел перед переходом к следующему.

Однако доступны и другие алгоритмы:

Консистентное хеширование позволяет направлять запросы на один и тот же узел в зависимости от некоторого значения: переменной NGINX, HTTP-заголовка, cookie и т.д.

Помните, что HTTP — это протокол без состояния, поэтому серверы приложений устанавливают cookie при первом ответе, чтобы отслеживать пользователя между HTTP-запросами. Это то, что мы называем "сессией". Нам нужно знать имя cookie сессии, используемого на сервере. Разные серверы приложений используют разные cookie:

  • JSESSIONID для серверов на основе JVM
  • PHPSESSID для PHP
  • ASPSESSIONID для ASP.Net
  • и т.д.

Я буду использовать обычный Tomcat, поэтому cookie сессии — это JSESSIONID. Соответственно, документация Apache APISIX для двух узлов выглядит следующим образом:

routes: - uri: /* upstream: nodes: "tomcat1:8080": 1 #1 "tomcat2:8080": 1 #1 type: chash #2 hash_on: cookie #3 key: cookie_JSESSIONID #4
  1. Определение вышестоящих узлов
  2. Выбор алгоритма консистентного хеширования
  3. Хеширование на основе cookie
  4. Определение, какой cookie использовать для хеширования

Заключение

В этой статье мы подробно рассмотрели постоянные сессии, необходимость использования репликации сессий вместе с постоянными сессиями и то, как реализовать постоянные сессии в Apache APISIX.

Для дальнейшего изучения:

Tags: