Проект представляет собой реализацию бэкенда и фронтенда интернет-магазина. Система построена на микросервисной архитектуре с использованием .NET 8, RabbitMQ, Redis, PostgreSQL и Next.js.
- Создание заказа: Асинхронный процесс. Заказ создается в статусе
New, и событие о создании отправляется в брокер сообщений (RabbitMQ). - Просмотр заказов: Получение списка заказов пользователя и детальной информации о конкретном заказе.
- Паттерн Transactional Outbox: Гарантирует атомарное сохранение заказа в БД и отправку события в RabbitMQ.
- Управление счетом: Создание счета пользователя и пополнение баланса.
- Обработка оплаты: Слушает события о создании заказа и списывает средства.
- Гарантии надежности:
- Transactional Inbox: Дедупликация входящих сообщений (Idempotency) для предотвращения повторного списания средств (Exactly-Once semantics).
- Concurrency Control: Optimistic Locking (через
RowVersion) для защиты от гонок (Race Conditions) при параллельных запросах к балансу.
- Real-time обновления: Использует SignalR (WebSockets) для мгновенного уведомления фронтенда об изменении статуса заказа (например, "Оплачено").
- Масштабируемость: Подключен Redis Backplane, что позволяет запускать несколько экземпляров сервиса уведомлений — клиенты получат сообщение независимо от того, к какому инстансу они подключены.
- Отдельное приложение на Next.js.
- Взаимодействует с микросервисами через API Gateway.
- Поддерживает WebSocket подключение для получения Push-уведомлений.
- Построен на Ocelot.
- Единая точка входа для всех запросов.
- Маршрутизация и балансировка нагрузки.
Проект разработан с строгим соблюдением принципов чистого кода и архитектурных паттернов.
- SRP (Single Responsibility Principle): Каждый микросервис отвечает строго за свой домен (Заказы не знают про баланс, Платежи не знают про состав заказа). Внутри кода: Контроллеры отвечают только за HTTP, Сервисы — за бизнес-логику, Consumer-ы — за обработку сообщений.
- OCP (Open/Closed Principle): Использование
MassTransitпозволяет добавлять новые обработчики событий (например, сервис логистики), не меняя код отправки событий вOrderService. - LSP (Liskov Substitution Principle): Используются абстракции (интерфейсы
IOrderService,IPaymentService), что позволяет легко подменять реализации (например, для тестов) без нарушения логики. - ISP (Interface Segregation Principle): Интерфейсы событий (
IOrderCreatedEvent) содержат только необходимые данные, не перегружая потребителей лишней информацией. - DIP (Dependency Inversion Principle): Все зависимости (DbContext, MassTransit Bus, Services) внедряются через Constructor Injection.
- Information Expert: Логика списания средств находится в
PaymentService, так как именно он владеет данными о счетах (Account). - Controller:
OrdersControllerиPaymentsControllerвыступают как фасад для бизнес-логики, принимая пользовательский ввод и делегируя работу сервисам. - Low Coupling: Сервисы общаются асинхронно через RabbitMQ, не имея прямых HTTP-зависимостей друг от друга.
Запуск всей инфраструктуры (БД, RabbitMQ, Redis, Бэкенд, Фронтенд):
docker-compose up -d --buildБлагодаря Stateless-архитектуре и использованию Redis/RabbitMQ, сервисы можно масштабировать горизонтально.
Пример запуска с 2 экземплярами сервиса заказов, 2 экземплярами сервиса оплат и 3 экземплярами сервиса уведомлений:
docker-compose up -d --build --scale orders-service=2 --scale payments-service=2 --scale notification-service=3Примечание: Ocelot Gateway автоматически распределяет нагрузку между инстансами (Round Robin), а Redis синхронизирует WebSockets между инстансами уведомлений.
После успешного запуска система доступна по следующим адресам:
| Сервис | URL | Описание |
|---|---|---|
| Frontend | http://localhost:3000 |
Веб-интерфейс магазина |
| API Gateway | http://localhost:5000 |
Единая точка входа для API |
| Swagger UI | http://localhost:5000/swagger |
Документация API (Общая документация по API) |
| RabbitMQ | http://localhost:15672 |
Админка брокера (guest/guest) |
Все запросы выполняются через Api Gateway на http://localhost:5000.
POST /orders— Создать новый заказ (запускает процесс оплаты).GET /orders/{id}— Получить информацию и статус конкретного заказа.GET /orders/user/{userId}— Получить историю заказов пользователя.
POST /payments/account— Создать счет (Account) для пользователя.POST /payments/deposit— Пополнить баланс счета.GET /payments/{userId}— Узнать текущий баланс пользователя.
POST /hub/notifications/negotiate— Инициализация соединения (SignalR Negotiation).GET /hub/notifications— Основной WebSocket Endpoint для подписки на уведомления.