# Stateless и stateful компоненты

← [Раздел](README.md) · [Главная](../README.md)

## Цель

Понять разницу **stateless** и **stateful** сервисов, как состояние сессии влияет на масштабирование и где хранить state в облаке.

## Предварительно

- [Вертикальное и горизонтальное](vertikalnoe-i-gorizontalnoe.md)

## Время

**3–4 часа**

---

## Определения

| | Stateless | Stateful |
|---|-----------|----------|
| Память между запросами | Не хранит бизнес-состояние | Хранит или владеет состоянием |
| Любая реплика | Обработает любой запрос* | Не всегда |
| Пример | REST API за LB | PostgreSQL, Redis с данными |
| Масштабирование | Добавить копии | Сложнее (репликация, шард) |

\*Если сессия вне инстанса (Redis/JWT).

---

## Stateless API — цель для горизонтали

```mermaid
flowchart LR
  LB[LB] --> A[API 1]
  LB --> B[API 2]
  A --> Redis[(Session store)]
  B --> Redis
  A --> DB[(DB)]
  B --> DB
```

Запрос 1 на API 1, запрос 2 на API 2 — **одинаковый** результат при общем хранилище сессий/данных.

---

## Где прячется state (ловушки)

| «Stateless» API, но… | Проблема |
|----------------------|----------|
| Сессия в памяти процесса | Sticky sessions ломают баланс |
| Локальный файл upload | Второй pod не видит файл |
| In-memory rate limit map | Лимит на каждой реплике × N |
| Singleton cron в коде | Дублируется на 3 pod |

**Решение:** вынести state в Redis, S3, БД; cron — один leader election.

---

## Sticky sessions (session affinity)

LB всегда шлёт пользователя на **один** pod.

| Плюс | Минус |
|------|-------|
| Можно lazy in-memory session | Неравномерная нагрузка |
| | Падение pod = потеря сессии |
| | Мешает scale down |

Предпочитайте **centralized session store** или JWT.

---

## Stateful: базы данных

Primary хранит **authoritative** state. Реплики — read-only или failover.

| Паттерн | Назначение |
|---------|------------|
| Primary + standby | HA failover |
| Read replicas | Масштаб чтения |
| Connection pooler | PgBouncer — много API, мало conn к DB |

Запись остаётся **узким местом** одного primary.

---

## Stateful: очереди и стримы

Брокер **помнит** очередь/offset:

| Система | State |
|---------|-------|
| RabbitMQ | Сообщения в queue |
| Kafka | Log partitions, consumer offset |

Масштабирование — больше partitions/consumers с правильным key.

---

## 12-factor: processes

Приложение как **набор stateless процессов**; состояние — в backing services (БД, cache, queue). Это философия, удобная для облака.

---

## Миграция монолита к stateless

| Шаг | Действие |
|-----|----------|
| 1 | Вынести сессии в Redis |
| 2 | Uploads в object storage |
| 3 | Убрать локальные кэши или сделать distributed cache |
| 4 | Добавить 2+ реплики за LB |
| 5 | Health checks: `/health`, `/ready` |

---

## Health checks для оркестратора

| Endpoint | Проверяет |
|----------|-----------|
| `/health` | Процесс жив |
| `/ready` | Может принимать трафик (БД доступна) |

K8s не шлёт трафик на pod, пока not ready — важно при старте и миграциях.

---

## Практика

1. Найдите 3 скрытых state в гипотетическом «stateless» API.  
2. JWT vs server session — плюсы для scale out (таблица).  
3. Зачем `/ready` отдельно от `/health`?

---

## Самопроверка

1. Можно ли масштабировать API с сессией только в RAM?  
2. PostgreSQL — stateless или stateful?  
3. Куда деть загруженные файлы при 3 репликах API?

---

## Дальше

→ [Балансировка нагрузки и кэш](balansirovka-i-kesh.md)
