Требования, SLO и архитектурная схема проекта

↑ Fullstack-практика

Желательно~6 мин чтенияУровень: middle+

Зачем это на собесе

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

Цель

Описать учебный production-проект Clinic (запись пациентов на приём): что он делает, для кого, какие нефункциональные требования и SLO, как выглядит архитектура и какие решения приняты (ADR). Этот документ — основа для всех следующих шагов: контракты, реализация, CI/CD, наблюдаемость и game day.

Продукт и пользователи

РольЗадачи
Пациентнайти врача и свободное время, записаться, отменить/перенести запись, получить напоминание
Регистраторуправлять расписанием, записывать по телефону, подтверждать/отменять
Врачвидеть свои приёмы на день, отмечать статус (принят, не явился)
Администраторсправочники (врачи, специальности, кабинеты), отчёты, роли

Основные сценарии (user journeys)

  1. Запись на приём: выбор специальности → врача → свободного слота → подтверждение → уведомление.
  2. Отмена/перенос записи с освобождением слота.
  3. Расписание врача на день/неделю.
  4. Вход через SSO (OIDC), разграничение ролей.

Функциональные требования (MVP)

  • каталог врачей и специальностей (чтение, поиск, фильтры);
  • слоты расписания: генерация по шаблону, бронирование без двойной записи (конкурентность!);
  • CRUD записей с правилами (нельзя записаться в прошлое, лимиты на пациента, окна отмены);
  • уведомления (email/SMS/Telegram) о записи и напоминания — асинхронно;
  • роли и права (пациент видит только свои записи);
  • аудит действий (кто и что изменил);
  • административный интерфейс справочников.

Нефункциональные требования

ОбластьТребование
Производительностьp95 API < 300 мс на чтении каталога, < 500 мс на записи; 200 RPS на пике (приём записей утром)
Доступность99.9% в месяц для API записи (≈ 43 мин простоя)
Надёжность данныхRPO ≤ 5 минут, RTO ≤ 1 час; запись не теряется и не дублируется
БезопасностьOIDC/PKCE, TLS везде, минимальные права, защита ПДн (152-ФЗ/GDPR): шифрование, маскирование в логах, аудит доступа
Масштабируемостьгоризонтальное для API; БД — вертикально + реплика чтения
Наблюдаемостьметрики, структурированные логи, трассировки, дашборды, алерты по SLO
Сопровождаемостьконтракты API, тесты, IaC, документация, ADR
Доступность интерфейсаWCAG AA, адаптивность (мобильные), i18n (ru/en)
Совместимостьпоследние 2 версии браузеров; мобильный Safari/Chrome

SLI и SLO

СценарийSLISLO (30 дней)
Доступность APIдоля ответов без 5xx / все запросы99.9%
Латентность чтениядоля запросов < 300 мс95%
Латентность записи на приёмдоля запросов < 500 мс95%
Корректность записидоля записей без конфликтов/дублей100% (инвариант, а не SLO: ошибки — баги)
Уведомлениядоля отправленных за 1 мин99%
FrontendLCP < 2.5 с для 75% сессий; доля сессий без JS-ошибок99% crash-free

Error budget API: 0.1% ≈ 43 минуты в месяц. Политика: при расходе > 50% — осторожные релизы, при исчерпании — заморозка фич и работа над надёжностью.

Архитектура

Браузер (Vue 3 + Quasar SPA)
   │ HTTPS
   ▼
Nginx / Ingress (TLS, маршрутизация, rate limit)
   ├── / → web (статика SPA)
   ├── /api → Clinic API (ASP.NET Core)
   └── /auth → Keycloak (OIDC)
Clinic API ──▶ PostgreSQL (основные данные)
   │       ├─▶ Redis (кэш расписания, блокировки, rate limit)
   │       └─▶ Outbox → брокер (RabbitMQ/Kafka) → Notification Worker → Email/SMS/Telegram
Телеметрия: OTel SDK → OTel Collector → Prometheus / Loki / Tempo (или ClickHouse) → Grafana

Компоненты и границы

  • Web (SPA): Vue 3, Quasar, Pinia, TanStack Query, Vue Router; OIDC (PKCE) через Keycloak; сгенерированный клиент API;
  • API: ASP.NET Core (Minimal API/Controllers), слои Domain/Application/Infrastructure; FluentValidation; EF Core; Polly; OpenTelemetry; health checks;
  • Worker: обработка outbox и рассылок; идемпотентные обработчики;
  • PostgreSQL: схема clinic, миграции (EF/Flyway), ограничения целостности, индексы;
  • Redis: кэш каталога/слотов (cache-aside), rate limiting;
  • Keycloak: пользователи, роли, SSO;
  • Инфраструктура: Docker, compose (dev), Kubernetes (prod) + Helm, GitLab CI, Terraform/Ansible.

Ключевые архитектурные решения (ADR)

ADRРешениеАльтернативыОбоснование
1Модульный монолит API + отдельный Workerмикросервисынебольшая команда, единая БД, проще эксплуатация; границы модулей для будущего разделения
2PostgreSQLMongoDBстрогие ограничения и транзакции для расписания
3Бронирование слота через уникальное ограничение + оптимистичная блокировкараспределённые блокировкицелостность на уровне БД, проще и надёжнее
4Transactional Outbox для уведомленийdual writeатомарность «запись + событие»
5OIDC Keycloak, PKCEсвой JWTстандарты, SSO, MFA
6OpenAPI как контракт (API-first) + кодогенерация клиентаручные типыединый источник истины
7OpenTelemetry + Prometheus/Grafana/Loki/Tempoвендорный APMстандарты, контроль стоимости
8Kubernetes + Helm + GitOpscompose на VMHA, rolling, автоскейл (на этапе роста)

Формат ADR: контекст → варианты → решение → последствия. Храним в docs/adr/.

Модель данных (упрощённо)

doctors(id, full_name, specialty_id, room, active)
specialties(id, name)
slots(id, doctor_id, starts_at timestamptz, duration_min, status)    -- free | booked | blocked
appointments(id, slot_id UNIQUE, patient_id, status, created_at, updated_at, version)
patients(id, user_sub, full_name, phone)        -- user_sub = sub из Keycloak
outbox(id, type, payload jsonb, created_at, published_at)
audit_log(id, actor, action, entity, entity_id, at, details jsonb)

Инвариант «один слот — одна активная запись»: UNIQUE (slot_id) WHERE status IN ('booked','confirmed') (частичный уникальный индекс).

Риски и допущения

  • пиковая нагрузка утром (старт записи на новый период): кэш, очередь, rate limiting;
  • ПДн: классификация данных, маскирование, права доступа, ретенция;
  • зависимость от SMS/Email провайдера: ретраи, очередь, деградация;
  • одиночный кластер → HA на уровне приложения и БД (реплика, бэкапы);
  • допущения и ограничения фиксируются в документе.

Что делаем

  • Описать роли, сценарии и MVP-границы (что не входит);
  • Зафиксировать нефункциональные требования с числами;
  • Определить SLI/SLO и error budget, политику при расходе;
  • Нарисовать архитектурную схему (C4: контекст и контейнеры) и сценарий запроса;
  • Оформить 6–8 ADR с альтернативами;
  • Спроектировать модель данных и ключевые инварианты;
  • Перечислить риски и план их снижения;
  • Определить стратегию окружений (dev/staging/prod), тестирования и релизов.

Результат / артефакты

  • docs/requirements.md (функциональные и нефункциональные требования, SLO);
  • docs/architecture.md + диаграммы (C4 context/container, последовательность записи на приём);
  • docs/adr/0001…0008-*.md;
  • схема БД (ER-диаграмма) и черновик миграций;
  • реестр рисков; definition of done для MVP.

Что рассказать на собесе

  • как из бизнес-сценариев получили измеримые требования и SLO, и как они повлияли на архитектуру (например, бронирование слота через ограничения БД, а не блокировки приложения);
  • почему модульный монолит, а не микросервисы, и когда будете разделять;
  • как обеспечен инвариант «нет двойной записи» при конкурентных запросах;
  • какие компромиссы приняты (ADR) и что изменилось бы при росте нагрузки;
  • как требования безопасности и ПДн отражены в дизайне.