PROD Final personal project
Find a file
2025-02-22 11:35:58 +03:00
api first commit 2025-02-22 11:35:58 +03:00
assets first commit 2025-02-22 11:35:58 +03:00
deployments first commit 2025-02-22 11:35:58 +03:00
internal first commit 2025-02-22 11:35:58 +03:00
scripts first commit 2025-02-22 11:35:58 +03:00
.cursorignore first commit 2025-02-22 11:35:58 +03:00
.dockerignore first commit 2025-02-22 11:35:58 +03:00
.gitignore first commit 2025-02-22 11:35:58 +03:00
.golangci.yml first commit 2025-02-22 11:35:58 +03:00
docker-compose.yml first commit 2025-02-22 11:35:58 +03:00
README.md first commit 2025-02-22 11:35:58 +03:00
taskfile.yml first commit 2025-02-22 11:35:58 +03:00

Ads Platform

Введение

Ads Platform EDA-платформа для управления рекламными кампаниями, статистикой, пользователями, рекламодателями и клиентами.

Ключевые сервисы:

  • Adservice: показ рекламы, обработка кликов.
  • Campaignservice: управление кампаниями.
  • Statisticservice: сбор и анализ статистики.
  • Userservice: управление пользователями, рекламодателями, клиентами и ML оценками.

Поддержка:

  • RabbitMQ (сообщения)
  • Postgres (основные данные)
  • Redis (кэш)
  • MongoDB (документы)
  • Minio (файлы)
  • Prometheus, Grafana, Tempo, Jaeger (мониторинг)

Схема

Схема

Запуск

Требования: Docker, Docker Compose

docker-compose up -d

docker-compose ps

Сервисы:

  • Adservice: http - 7004, grpc - 6012
  • Campaignservice: http - 7001, grpc - 6010
  • Statisticservice: http - 7006, grpc - 6011
  • Userservice: http - 7000, grpc - 6009
  • Доп.: RabbitMQ (5672/15672), Prometheus (9090), Grafana (3000)...

Пути

Userservice:

  • POST /api/v1/advertisers/bulk создать рекламодателей
  • POST /api/v1/clients/bulk создать клиентов

Campaignservice:

  • POST /api/v1/advertisers/{advertiser_id}/campaigns создать кампанию
  • POST /api/v1/advertisers/{advertiser_id}/campaigns/image кампания с изображением
  • POST /api/v1/advertisers/{advertiser_id}/campaigns/text кампания с текстом
  • GET/PUT/DELETE /api/v1/advertisers/{advertiser_id}/campaigns/{campaign_id} управление кампанией

Statisticservice:

  • GET /api/v1/stats/advertisers/{advertiser_id}/campaigns статистика кампаний
  • GET /api/v1/stats/advertisers/{advertiser_id}/campaigns/daily ежедневная статистика
  • GET /api/v1/stats/campaigns/{campaign_id} детальная статистика
  • GET /api/v1/stats/campaigns/{campaign_id}/daily ежедневная детальная статистика

Adservice:

  • GET /api/v1/ads получить рекламу (client_id)
  • POST /api/v1/ads/{ad_id}/click регистрировать клик
  • POST /api/v1/time/advance имитация сдвига времени

Схема данных

Ниже представлены основные таблицы и связи между сущностями, используемые для хранения данных в нашей СУБД (PostgreSQL):

Таблица Clients (clients)

Поле Тип Описание
client_id UUID Уникальный идентификатор клиента. Используется для однозначной идентификации пользователя.
login VARCHAR Имя пользователя или логин, используемый для доступа к сервисам.
age INTEGER Возраст клиента, используется для таргетинга рекламы.
gender VARCHAR Пол клиента (например, M/F), используется при таргетинге.
location VARCHAR Географическое местоположение клиента.
created_at TIMESTAMP Дата и время создания записи.

Комментарий: Таблица Clients хранит базовую информацию о пользователях, взаимодействующих с платформой рекламы.

Таблица Advertisers (advertisers)

Поле Тип Описание
advertiser_id UUID Уникальный идентификатор рекламодателя.
name VARCHAR Название или бренд рекламодателя.
created_at TIMESTAMP Дата создания рекламодателя.

Комментарий: Таблица Advertisers содержит сведения о рекламодателях, которые запускают рекламные кампании. Один рекламодатель может иметь несколько кампаний.

Таблица Campaigns (campaigns)

Поле Тип Описание
campaign_id UUID Уникальный идентификатор кампании.
advertiser_id UUID Внешний ключ, связывающий кампанию с таблицей Advertisers.
impressions_limit INTEGER Максимальное количество показов (impressions) для кампании.
clicks_limit INTEGER Максимальное количество кликов для кампании.
cost_per_impression DECIMAL Стоимость одного показа рекламы.
cost_per_click DECIMAL Стоимость одного клика по рекламе.
ad_title VARCHAR Заголовок рекламного объявления.
ad_text TEXT Текстовое содержание объявления.
start_date TIMESTAMP или INT Дата начала активности кампании.
end_date TIMESTAMP или INT Дата окончания активности кампании.
targeting JSONB Настройки таргетинга (например, возраст, пол, локация).
created_at TIMESTAMP Дата создания кампании.

Комментарий: Таблица Campaigns отвечает за хранение информации о рекламных кампаниях. Каждый рекламодатель может иметь несколько кампаний, что реализуется через внешний ключ advertiser_id. Параметры impressions_limit и clicks_limit задают ограничения по показам и кликам, а cost_per_impression и cost_per_click определяют стоимость данных действий.

Таблица MLScores (ml_scores)

Поле Тип Описание
ml_score_id UUID Уникальный идентификатор записи оценки.
advertiser_id UUID Внешний ключ, связывающий оценку с таблицей Advertisers.
client_id UUID Внешний ключ, связывающий оценку с таблицей Clients.
score INTEGER Значение оценки, определяющее релевантность рекламы для клиента.
created_at TIMESTAMP Дата создания записи оценки.

Комментарий: Таблица MLScores используется для хранения оценок, рассчитанных с помощью машинного обучения. Эти оценки помогают ранжировать рекламные кампании и определять, насколько предложение соответствует интересам конкретного клиента.

Связи между таблицами

  • Clients и MLScores: Один клиент может иметь несколько оценок (по каждому рекламодателю), что помогает персонализировать показ рекламы.
  • Advertisers и Campaigns: Один рекламодатель может создавать множество кампаний, что реализуется через внешний ключ advertiser_id в таблице Campaigns.
  • Advertisers и MLScores: Рекламодатель может иметь несколько оценок, связанных с различными клиентами.

API

  • Userservice: управление рекламодателями, клиентами, ML оценками.
  • Adservice: показ рекламы и клики.
  • Campaignservice: создание и управление кампаниями.
  • Statisticservice: предоставление статистики.

Выбор технологий

  • Postgres: надежное хранение реляционных данных. (кто-то еще юзает MySQL?)
  • Redis: быстрый кэш. Тупо база
  • MongoDB: гибкое хранение документов. Для сервисов, где трафик преимущественно на чтение.
  • RabbitMQ: асинхронные сообщения. быстрее для настройки чем Kafka.
  • Minio: S3-хранилище для файлов. Удобно, S3-совместимое.
  • Мониторинг: Prometheus, Grafana, Tempo, Jaeger. Тупо база чтобы быстро мониторить что за херня произошла у клиента прямо с телефончика пока сидишь в старбаксе.

Прогнозируемая нагрузка в продакшене

Сервис Эндпоинт Запросов/час
Userservice POST /api/v1/advertisers/bulk 50500
Userservice GET /api/v1/advertisers/{id} 25005000
Userservice POST /api/v1/clients/bulk 50500
Userservice GET /api/v1/clients/{id} 500015000
Userservice POST /api/v1/ml-scores 15002500
Adservice GET /api/v1/ads 2500050000
Adservice POST /api/v1/ads/{ad_id}/click 1000025000
Adservice POST /api/v1/time/advance 2550
Campaignservice GET /api/v1/advertisers/{advertiser_id}/campaigns 500025000
Campaignservice POST /api/v1/advertisers/{advertiser_id}/campaigns 50250
Campaignservice POST /api/v1/advertisers/{advertiser_id}/campaigns/image 50250
Campaignservice POST /api/v1/advertisers/{advertiser_id}/campaigns/text 50250
Campaignservice GET /api/v1/advertisers/{advertiser_id}/campaigns/{campaign_id} 250010000
Campaignservice PUT /api/v1/advertisers/{advertiser_id}/campaigns/{campaign_id} 50250
Campaignservice DELETE /api/v1/advertisers/{advertiser_id}/campaigns/{campaign_id} 25100
Statisticservice GET /api/v1/stats/advertisers/{advertiser_id}/campaigns 500015000
Statisticservice GET /api/v1/stats/advertisers/{advertiser_id}/campaigns/daily 25007500
Statisticservice GET /api/v1/stats/campaigns/{campaign_id} 250010000
Statisticservice GET /api/v1/stats/campaigns/{campaign_id}/daily 15005000

Тестирование

Доступны unit, load и e2e тесты. Правда успел сделать только для userservice. Запуск тестов происходит через testcontainers.

task unit-test

task load-test

task e2e-test

Мониторинг

Алгоритм показа рекламы

При получении запроса на показ рекламы происходит следующий алгоритм:

  1. Получение данных клиента:

    • Сначала происходит попытка извлечения информации о клиенте из кеша (Redis).
    • Если клиент не найден в кеше, данные ищутся в базе данных (MongoDB) и затем сохраняются в кеш для ускорения будущих запросов.
  2. Получение активных рекламных кампаний:

    • Производится фильтрация кампаний по критериям таргетинга: возраст, пол, локация, а также проверка дат начала и окончания кампании.
  3. Получение ML оценок (ML Scores):

    • Извлекаются оценки релевантности для рекламодателей, что используется для определения интереса клиента к рекламным объявлениям.
  4. Ранжирование рекламных кампаний:

    • Рекламные кампании анализируются и ранжируются с использованием Recommendation Engine.
    • При расчёте рейтинга учитываются такие параметры, как ожидаемая прибыль, релевантность (на основе ML Score), уровень выполнения по импрессиям и кликам, а также фактор свежести кампании.
  5. Выбор и отображение рекламы:

    • Выбирается кампания с наивысшим рейтингом.
    • Асинхронно обновляются статистические данные (увеличивается счётчик показов, impressions) в фоновом режиме.
    • Формируется ответ, содержащий информацию о выбранном объявлении для отображения клиенту.

Ниже приведена блок-схема, иллюстрирующая данный алгоритм:

flowchart TD
    A[Получение запроса на показ рекламы] --> B[Получить данные клиента]
    B --> C{Клиент найден в Redis?}
    C -- Да --> D[Использовать данные из Redis]
    C -- Нет --> E[Поиск клиента в MongoDB]
    E --> F[Сохранить данные в Redis]
    D & F --> G[Получить активные кампании по таргетингу]
    G --> H[Получить ML Scores для клиента]
    H --> I[Ранжировать кампании в Recommendation Engine]
    I --> J[Выбрать кампанию с наивысшим рейтингом]
    J --> K[Асинхронное обновление статистики (impressions)]
    K --> L[Формирование ответа с выбранным объявлением]
    L --> M[Отправка ответа клиенту]

Также представлена диаграмма последовательности для основного запроса на показ рекламы:

sequenceDiagram
    participant C as Клиент
    participant AS as Ad Service
    participant R as Redis
    participant M as MongoDB
    participant RM as Recommendation Engine

    C->>AS: Запрос рекламы (client_id)
    AS->>R: Получение данных клиента
    alt Клиент найден
      R-->>AS: Данные клиента
    else Клиент не найден
      AS->>M: Поиск клиента
      M-->>AS: Данные клиента
      AS->>R: Кэширование данных
    end
    AS->>M: Получение активных кампаний
    AS->>M: Получение ML Scores
    AS->>RM: Ранжирование кампаний
    RM-->>AS: Выбранная кампания
    AS->>AS: Асинхронное обновление статистики
    AS-->>C: Отправка объявления