- Создать скелеты сервисов cart и loms, согласно документации.
- Структуру проекта сделать с учетом разбиения на слои, бизнес-логику писать отвязанной от реализаций клиентов и хендлеров.
- Все хендлеры отвечают просто заглушками.
- Все межсервисные вызовы выполняются. Если хендлер по описанию из документации должен ходить в другой сервис, он должен у вас это успешно делать в коде.
- Должны успешно проходить make precommit и make run-all в корневой папке.
- Наладить общение с product-service (в хендлерах cart.item.add, cart.list). Токен авторизации брать из запроса и пробрасывать в контекст.
- 💎 На алмаз реализовать in-memory хранилище для сервисов cart и loms;
Перевести всё взаимодействие c сервисами на протокол gRPC. Для этого:
- Создать protobuf контракты сервисов
- В каждом проекте нужно добавить в Makefile команды для генерации .go фалйло из proto файлов и установки нужных зависимостей (можно использовать protoc или buf на на свое усмотрение).
- Сгенерировать клиентов и сервисы
- Использовать разделение на слои, созданное ранее, заменив слой HTTP на GRPC.
- Взаимодействие по HTTP полностью удалить и оставить только gRPC.
Дополнительное задание:
- добавить HTTP-gateway и валидацию protobuf сообщений - 1💎
- добавить swagger-ui и возможность совершать запросы из сваггера к сервису (поднять swagger-ui сервер) - 1💎
- Для каждого сервиса(где необходимо что-то сохранять/брать) поднять отдельную БД в docker-compose.
- Сделать миграции в каждом сервисе (достаточно папки миграций и скрипта).
- Создать необходимые таблицы.
- Реализовать логику репозитория в каждом сервисе. (Рекомендуется использовать plain sql, без query билдеров, однако приветствуется генерация по типу sqlc)
- Драйвер для работы с postgresql: только pgx (pool).
- В одном из сервисов сделать транзакционность запросов (как на воркшопе).
Задание на алмазик:
💎 Для каждой БД полнять свой балансировщик (pgbouncer или odyssey, можно и то и то). Сервисы ходят не на прямую в БД, а через балансировщик
- Необходимо уменьшить время ответа cart.List при помощи конкурентности. К этой части задания есть следующие требования:
- Для решения обязательно надо написать какую-либо собственную имплементацию конкурентного паттерна/структуры. Намеренно не ограничиваем в выборе, оригинальные идеи приветствуются. Логичной структурой будет Worker Pool
- Вся имплементация обязательно должна быть покрыта комментариями о том, как она работает и на какие гарантии в каких местах вы рассчитываете. Это улучшит ваше понимание паттернов и одновременно облегчит работу тьюторов
- Во внешних походах к Product Service необходимо ограничить рейт запросов, т.е. настроить рейт-лимитер. Рейт-лимитер обязательно сделать в виде grpc интерцептора. Ограничить надо именно общее кол-во походов в единицу времени, а не одновременное кол-во активных запросов. Target RPS - 10 RPS.
- В приложениях по всем слоям необходимо прокинуть контексты. Все контексты в рамках одного запроса должны быть связаны
Задания на алмазик:
- 💎 Сделать аннулирование заказов старше 10 минут в фоне через горутину, не отдельный процесс-демон
- 💎 Синхронизировать рейт-лимитер внешних походов через единую сущность (в т.ч. между различными подами). В качестве внешнего хранилища можно использовать как Postgres, так и Redis (или любое другое хранилище, с которым вам комфортно работать)
Необходимо обеспечить покрытие логики ручек сервиса (cart или loms) модульными тестами. Общий уровень покрытия сервиса (по statements) должнен составлять не менее 70%. Генерацию моков осуществлять любыми удобными средствами (mockery, minimock, gomock, etc...).
Задание на алмазик: 💎 Добавить интеграционные тесты для проверки взаимодействия с базой данных для сервиса (cart или loms). Интеграционные тесты (и развертывание тестового окружения) должны запускаться при помощи скрипта.
- Развернуть kafka кластер в docker-compose.
- Интегрировать LOMS с кафкой: LOMS пишет в кафку изменения статуса заказа (создание/отмена).
- Создать сервис нотификаций(просто main с консьюмер группой достаточно). Сервис нотификаций должен вычитывать сообщения о статусе заказа и отправлять нотификации об изменениях статуса заказа (просто писать в лог сообщение с номером заказа и статусом).
- Обеспечить гарантию отправки сообщения о статусе заказа (отказоустойчевый кластер/реплики, ack и вот это все).
- Обеспечить упорядоченную обработку статусов одного заказа (добиться упорядоченной отправки событий по заказу и чтение событий по заказу).
- Обеспечbть семантику exectly once (рассказывал как)
- 💎 Применить паттерн Outbox.
- Перевести логи всех сервисов на структурные с помощью библиотеки zap (лучше всего). Должны учитываться уровни логирования и все принципы форматирования логов.
- Настроить подъем Jaeger в docker-compose вместе с другими сервисами. Должен быть доступ к Jaeger UI.
- Покрыть трейсами один сценарий — ручка чекаута. Должен быть общий трейс между участвующими сервисами. Можно использовать готовые интерсепторы. На спаны стоит накинуть пару любых тегов (но не перс. данные).
- Настроить отдачу сервисами метрик и их сбор Prometheus, запущенным в отдельном контейнере.
- Настроить сбор метрик по 4 золотым сигналам:
Traffic
- rps по ручкам (http_requests_total). С лейблами на разные ручки и коды ответов;Latency
- разбивка по времени ответа запросов;Errors
- процент ошибок всех запросов;Saturation
- количество горутин;- Добавить метрик по желанию (бизнес-метрики, больше лейблов и т. д.).
- 💎 Сделать универсальную платформенную библиотеку, через которую удобно было бы создавать grpc-клиенты, уже обернутые метриками и базовыми трейсами, плюс удобно было бы оборачивать метриками и трейсами grpc-сервер. (С такой библиотекой можно сильно упростить себе жизнь в первых задачах, так как с ней можно покрыть сразу все сервисы).
- 💎 Самим разобраться с графаной и сделать графики 4 золотых сигналов.
Реализовать кеширование в сервисе через Redis:
- Поднять Redis в docker-compose.
- Решить что кешировать и как, исходя из специфики системы, свой выбор обосновать (написать 1-2 предложения в README.md);
- Реализовать данное кеширование. Не нужно кешировать все, здесь достаточно одного типа данных.
Реализовать шардирование кеша:
- В docker-compose поднять два (или более) контейнеров Redis на разных портах (один контейнер будет представлять собой один шард);
- Решить как шардировать кешируемые данные и свой выбор обосновать (написать 1-2 предложения в README.md);
- Реализовать данное шардирование.
💎 Спроектировать систему (написать примерно 1-2 абзаца в README.md)
Взять часть любой существующей системы (например, комментарии на YouTube, лента новостей в Twitter и т.д. что вам нравится) и описать, как бы вы ее спроектировали и почему именно так.
- Ответить как минимум на следующие вопросы:
- Кто потребители системы?
- Какие свойства критически важны для этой системы, а какие не очень?
- В зависимости от установленных приоритетных свойств описать:
- Какие будут сервисы, на чем они будет написаны, что будут делать и как будут масштабированы?
- Какие будут системы хранения данных, что будут хранить и как будут масштабированы?
- Какие еще компоненты системы следует реализовать и почему (LB, RL и т.д.)?
- Нарисовать схему или описать, как это все будет друг с другом взаимодействовать.
💎 Улучшить код с помощью профайлинга (подкрепить результатами профайлинга "до" и "после" в README.md)
- Разобраться с профайлингом;
- Изучить скорость работы любого своего сервиса с помощью профайлинга;
- Найти узкие места в коде;
- Ускорить сервис, улучшив алгоритм в проблемных местах (можно тривиально, главное - понять, как работает профайлинг)