# Синхронные вызовы

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

## Цель

Понять **синхронное взаимодействие** по HTTP/REST и gRPC: цепочки запрос-ответ, таймауты, идемпотентность и каскадные сбои.

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

- [API и шлюзы](../02-komponenty/api-i-shlyuzy.md)

## Время

**3–4 часа**

---

## Модель «запрос — ответ»

Клиент **блокируется** до ответа сервера. В облаке это:

- браузер → API;
- API → другой микросервис;
- API → внешний SaaS (sync).

```mermaid
sequenceDiagram
  participant C as Клиент
  participant A as API Lists
  participant U as API Users
  participant DB as PostgreSQL
  C->>A: GET /lists/1
  A->>U: GET /users/42 (sync)
  U->>DB: SELECT profile
  DB-->>U: row
  U-->>A: 200 JSON
  A->>DB: SELECT list
  DB-->>A: rows
  A-->>C: 200 aggregated JSON
```

---

## Когда синхрон уместен

| Сценарий | Почему sync |
|----------|-------------|
| Авторизация | Без токена нельзя продолжать |
| Чтение списка для экрана | UI ждёт данные |
| Проверка остатка перед оплатой | Нужен ответ сейчас |
| Валидация уникальности email | Немедленный 409 Conflict |

---

## HTTP как транспорт

| Аспект | Практика |
|--------|----------|
| Таймаут клиента | 5–30 с (меньше для UX) |
| Таймаут сервера к downstream | Меньше клиентского |
| Retry | Только на idempotent GET; POST — с Idempotency-Key |
| Connection pooling | Переиспользование TCP к БД и сервисам |

---

## gRPC (внутренний sync)

| HTTP/JSON | gRPC |
|-----------|------|
| Текст, универсален | Бинарный Protobuf |
| Удобен для браузера | Чаще сервис-сервис |
| OpenAPI | .proto контракт |

Для публичного mobile/web чаще **REST**; внутри mesh — **gRPC** для скорости и строгих типов.

---

## Цепочки вызовов и latency

Latency **складывается**: 50+30+40 = 120 ms только на сеть. При 4 уровнях p95 взрывается.

| Митигация | Как |
|-----------|-----|
| Агрегация в одном сервисе | BFF отдаёт один ответ |
| Параллельные вызовы | `Promise.all` / goroutines |
| Кэш | Профиль пользователя в Redis |
| Денормализация | Имя владельца в документе списка |

---

## Каскадные отказа

Если **Users** недоступен, падает и **Lists** — **каскад**.

```mermaid
flowchart TB
  A[API Lists] -->|timeout| B[API Users]
  B -->|down| X[❌]
  A -->|fail| C[Клиент 500]
```

**Circuit breaker:** после N ошибок перестаём звонить в Users, отдаём degraded ответ или fallback из кэша.

| Состояние breaker | Поведение |
|-------------------|-----------|
| Closed | Нормальные вызовы |
| Open | Быстрый fail без вызова |
| Half-open | Пробный запрос |

---

## Согласованность при sync

Одна транзакция в одной БД — **strong consistency**.  
Sync между двумя сервисами с двумя БД — **распределённая транзакция** (2PC) редка; чаще **Saga** (компенсирующие шаги) — тема продвинутых курсов.

Для новичка: **не делить данные** между сервисами, пока не болит.

---

## Идемпотентность

| Метод | Идемпотентен? |
|-------|---------------|
| GET | Да |
| PUT (полная замена) | Да |
| DELETE | Да (повтор — 404 ок) |
| POST | Нет по умолчанию |

Платежи: клиент шлёт `Idempotency-Key: uuid` — повтор не списывает дважды.

---

## Наблюдаемость sync-цепочек

**Distributed tracing:** один `trace_id` через все hop — Jaeger, Tempo, OpenTelemetry.

| Span | Сервис |
|------|--------|
| root | API Gateway |
| child | Lists |
| child | Users |

Без trace_id в логах разбор «кто виноват в 2s latency» — угадайка.

---

## Практика

1. Для GET `/lists/1` с профилем владельца: один sync vs параллель два вызова — сравните latency на бумаге.  
2. Что вернуть, если Users down, но список есть? (продуктовое решение)  
3. Укажите таймауты: клиент 10s, Lists→Users 2s.

---

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

1. Почему длинные цепочки sync опасны при пиковой нагрузке?  
2. Что делает circuit breaker в состоянии Open?  
3. Зачем Idempotency-Key для POST оплаты?

---

## Дальше

→ [Асинхрон и очереди](asinhron-i-ocheredi.md)
