Stateless-сервисы и почему это важно

Сервис без памяти о клиенте легко клонировать, заменять и масштабировать — в этом вся сила.

Stateless-сервис — сервис, который не хранит состояние между запросами в своей памяти: каждый запрос самодостаточен, и любой инстанс обработает его одинаково.

Stateful против stateless

Представьте корзину покупок. В stateful-варианте сервер хранит корзину в своей памяти. Тогда клиент обязан возвращаться на тот же сервер, иначе корзина «потеряется». В stateless-варианте корзина лежит в общем хранилище (Redis, БД), а сервер при каждом запросе читает её оттуда. Теперь любой инстанс обслужит клиента одинаково.

СвойствоStatefulStateless
Где состояниев памяти узлаво внешнем хранилище
Привязка клиентанужна (sticky)не нужна
Масштабированиетрудноетривиальное — клонируй инстансы
Падение узлапотеря сессий на нёмнезаметно, запрос уходит на другой
Деплойсложный, теряем состояниеrolling update без боли

Почему это ключ к масштабированию

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

Куда выносить состояние

Вид состоянияКуда вынести
Сессия / токен входаRedis, или подписанный JWT у клиента
Корзина, временные данныеRedis / Memcached
Постоянные данныебаза данных
Файлы, картинкиобъектное хранилище (S3) / CDN

JWT как пример stateless-аутентификации

Вместо хранения сессии на сервере выдаём клиенту подписанный токен. В нём зашит идентификатор пользователя; сервер проверяет подпись и не обращается к общему хранилищу. Запрос самодостаточен — любой инстанс проверит токен сам.

{
  "sub": "user-42",
  "role": "editor",
  "exp": 1718380800
}

Компромисс: такой токен трудно отозвать до истечения срока (сервер «не помнит» сессий), поэтому делают короткий срок жизни и refresh-токены.

Не всё бывает stateless

Базы данных, очереди, кэши — по природе stateful: они и есть состояние. Идея не в том, чтобы убрать состояние совсем, а в том, чтобы сосредоточить его в специально спроектированных хранилищах, а слой бизнес-логики держать stateless и легко масштабируемым.

Итог

  • Stateless-сервис не помнит клиента между запросами — любой инстанс взаимозаменяем.
  • Это делает масштабирование, автоскейлинг и переживание отказов простыми.
  • Состояние выносят в Redis/БД/объектное хранилище; логику держат stateless.
Проверьте себя
1. Почему stateless-сервисы легко масштабировать горизонтально?
AОни потребляют меньше памяти
BЛюбой инстанс взаимозаменяем — запрос можно отправить на любой узел
CОни не используют сеть
DОни не нуждаются в базе данных
2. Куда правильно вынести пользовательскую сессию из памяти сервера?
AВ локальный файл на каждом узле
BВо внешнее общее хранилище (Redis) или в подписанный JWT у клиента
CВ оперативную память балансировщика
DНикуда, сессии нельзя выносить
3. Какой компромисс у stateless-аутентификации через JWT?
AТокен невозможно проверить
BТокен трудно отозвать до истечения срока, так как сервер не хранит сессий
CJWT работает только в монолите
DJWT требует sticky sessions
Поддержать проект