Приложение для поиска мероприятий и единомышленников: пользователи создают события, находят компанию для участия в них, оставляют заявки, комментируют и получают персональные рекомендации на основе своей активности.
Проект построен как набор Spring Boot микросервисов, взаимодействующих через REST, gRPC и Apache Kafka, с централизованным Service Discovery и Config Server.
Приложение разбито на три группы сервисов:
| Сервис | Назначение |
|---|---|
discovery-server |
Service Discovery на базе Netflix Eureka — регистрация и обнаружение всех остальных сервисов |
config-server |
Централизованное хранение конфигурации (Spring Cloud Config) |
gateway-server |
Единая точка входа, маршрутизация запросов к core-сервисам |
| Сервис | Назначение |
|---|---|
user-service |
Управление пользователями |
category-service |
Управление категориями мероприятий |
event-service |
Мероприятия, подборки (compilations), публичный/приватный/административный API |
request-service |
Заявки на участие в мероприятиях |
comment-service |
Комментарии к опубликованным мероприятиям |
| Сервис | Назначение |
|---|---|
collector |
Принимает действия пользователей (просмотр/заявка/лайк) по gRPC, публикует их в Kafka в формате Avro |
aggregator |
Читает поток действий из Kafka, рассчитывает коэффициент косинусного сходства мероприятий, публикует результат в Kafka |
analyzer |
Хранит историю взаимодействий и коэффициенты сходства в PostgreSQL, отдаёт рекомендации по gRPC |
stats-server |
Классический сервис статистики посещений (сохранён с первого этапа) |
Внутренние gRPC-клиенты для Collector и Analyzer вынесены в отдельный модуль stats-client, контракты — в stats-proto (Protobuf) и stats-dto (Avro-схемы).
Реализована инфраструктура для сбора и анализа данных о посещаемости ресурсов: хранилище хитов по эндпоинтам, расчёт уникальных просмотров по IP, агрегация за произвольный период, HTTP-клиент для интеграции со сновным сервисом.
Реализована вся бизнес-логика согласно спецификации API:
- Публичный API — поиск мероприятий с динамической фильтрацией (QueryDSL).
- Приватный API — управление своими мероприятиями, участие в чужих, подтверждение заявок.
- Административный API — модерация контента, справочники категорий и пользователей.
- Многоуровневая валидация бизнес-правил (временные интервалы, лимиты участия, статусы модерации).
Добавлена система комментариев к опубликованным мероприятиям.
- Статусы модерации:
PENDING,PUBLISHED,REJECTED. - Проверка владения — редактировать комментарий может только автор.
FetchType.LAZYи отсутствие рекурсивных связей в сущностях для производительности БД.
Проект переведён на микросервисную архитектуру: каждый core-модуль выделен в отдельный Spring Boot сервис, добавлены Eureka и Config Server, взаимодействие между сервисами через Feign/gRPC-клиенты вместо прямых вызовов.
Реализована рекомендательная система из трёх сервисов:
- Collector принимает действия пользователей по gRPC (
ACTION_VIEW,ACTION_REGISTER,ACTION_LIKE) и пишет их в топик Kafkastats.user-actions.v1в формате Avro. - Aggregator инкрементально пересчитывает косинусное сходство мероприятий при каждом новом действии, не пересчитывая с нуля — обновляются только частичные суммы весов и суммы минимальных весов пар мероприятий. Результат публикуется в топик
stats.events-similarity.v1. - Analyzer строит на основе накопленных данных персональные рекомендации по трём алгоритмам: похожие мероприятия, предсказание оценки методом ближайших соседей, сумма весов взаимодействий (для рейтинга мероприятия).
event-service теперь запрашивает рейтинг мероприятия и рекомендации через gRPC-клиент к Analyzer вместо статичного счётчика просмотров; request-service отправляет события о регистрации на мероприятие в Collector.
| Категория | Технологии |
|---|---|
| Язык разработки | Java 21 |
| Фреймворк | Spring Boot, Spring Cloud (Eureka, Config, Gateway) |
| Межсервисное взаимодействие | REST, gRPC (Protobuf), Apache Kafka (Avro) |
| Сборка проекта | Maven (multi-module) |
| База данных | PostgreSQL (отдельная БД на каждый сервис) |
| Работа с данными | Spring Data JPA, QueryDSL |
| Маппинг и генерация кода | MapStruct, Lombok |
| Контейнеризация | Docker, Docker Compose |
mvn clean package
docker-compose up --buildПосле старта:
- Eureka Dashboard —
http://localhost:8761 - Config Server —
http://localhost:8888 - Gateway —
http://localhost:8080 - Stats-сервисы: Collector (
8088), Aggregator (8089), Analyzer (8090)
Спецификации API — ewm-main-service-spec.json и ewm-stats-service-spec.json в корне репозитория.
Полный список эндпоинтов — в ewm-main-service-spec.json. Публичный API поддерживает поиск и фильтрацию мероприятий, приватный — управление своими мероприятиями и заявками, административный — модерацию и справочники.
Дополнительно у мероприятия появились:
GET /events/recommendations— рекомендации мероприятий для пользователя (заголовокX-EWM-USER-ID).PUT /events/{eventId}/like— лайк посещённого мероприятия (400, если пользователь не был на мероприятии).
Административный API
GET /admin/comments— поиск с фильтрацией (текст, авторы, событие, статус, диапазон дат, пагинация).PATCH /admin/comments/{commentId}— изменение статуса модерации.DELETE /admin/comments/{commentId}— удаление любого комментария.
Публичный API
GET /comments— поиск опубликованных комментариев с фильтрацией и сортировкой по дате.GET /comments/{commentId}— получение опубликованного комментария.
Приватный API
POST /users/{userId}/events/{eventId}/comment— добавить комментарий к опубликованному мероприятию.GET /users/{userId}/comments— все комментарии пользователя.GET /users/{userId}/events/{eventId}/comments— комментарии пользователя к конкретному мероприятию.GET /users/{userId}/comments/{commentId}— комментарий пользователя по идентификатору.PATCH /users/{userId}/comments/{commentId}— редактирование своего комментария.DELETE /users/{userId}/comments/{commentId}— удаление своего комментария.
Collector — stats.service.collector.UserActionController
CollectUserAction— приём действия пользователя (просмотр, заявка, лайк).
Analyzer — stats.service.dashboard.RecommendationsController
GetRecommendationsForUser— поток рекомендованных мероприятий с предсказанной оценкой.GetSimilarEvents— поток мероприятий, похожих на указанное, с которыми пользователь ещё не взаимодействовал.GetInteractionsCount— суммарный вес взаимодействий по списку мероприятий (используется для рейтинга).