Курсовой проект 2024 года курса «Разработка high-load систем» Корпоративной магистерской программы «Распределённые веб-сервисы / Web scale systems».
Форкните проект, склонируйте и добавьте upstream
:
$ git clone [email protected]:<username>/2024-highload-dht.git
Cloning into '2024-highload-dht'...
...
$ git remote add upstream [email protected]:polis-vk/2024-highload-dht.git
$ git fetch upstream
From github.com:polis-vk/2024-highload-dht
* [new branch] main -> upstream/main
Так можно запустить тесты:
$ ./gradlew test
А вот так -- сервер:
$ ./gradlew run
Откройте в IDE -- IntelliJ IDEA Community Edition нам будет достаточно.
ВНИМАНИЕ! При запуске тестов или сервера в IDE необходимо передавать Java опцию -Xmx128m
.
В своём Java package ru.vk.itmo.test.<username>
реализуйте интерфейсы Service
и ServiceFactory.Factory
и поддержите следующий HTTP REST API протокол:
- HTTP
GET /v0/entity?id=<ID>
-- получить данные по ключу<ID>
. Возвращает200 OK
и данные или404 Not Found
. - HTTP
PUT /v0/entity?id=<ID>
-- создать/перезаписать (upsert) данные по ключу<ID>
. Возвращает201 Created
. - HTTP
DELETE /v0/entity?id=<ID>
-- удалить данные по ключу<ID>
. Возвращает202 Accepted
.
Используйте свою реализацию Dao
из предыдущего курса 2023-nosql-lsm
или референсную реализацию, если своей нет.
Проведите нагрузочное тестирование с помощью wrk2 в одно соединение:
PUT
запросами на стабильной нагрузке (wrk2
должен обеспечивать заданный с помощью-R
rate запросов) ниже точки разладкиGET
запросами на стабильной нагрузке по наполненной БД ниже точки разладки
Нагрузочное тестирование и профилирование должны проводиться в одинаковых условиях (при одинаковой нагрузке на CPU). А почему не curl
/F5, можно узнать здесь и здесь.
Приложите полученный консольный вывод wrk2
для обоих видов нагрузки.
Отпрофилируйте приложение (CPU и alloc) под PUT
и GET
нагрузкой с помощью async-profiler.
Приложите SVG-файлы FlameGraph cpu
/alloc
для PUT
/GET
нагрузки.
Объясните результаты нагрузочного тестирования и профилирования и приложите текстовый отчёт (в Markdown). Все используемые инструменты были рассмотрены на лекции -- смотрите видео запись.
Продолжайте запускать тесты и исправлять ошибки, не забывая подтягивать новые тесты и фиксы из upstream
.
Если заметите ошибку в upstream
, заводите баг и присылайте pull request ;)
Когда всё будет готово, присылайте pull request со своей реализацией, результатами профилирования, отчётом с их анализом и проведёнными по результату профилирования оптимизациями на review. На всех этапах оценивается и код, и анализ (отчёт) -- без анализа полученных результатов работа оценивается минимальным количеством баллов. Не забывайте отвечать на комментарии в PR (в том числе автоматизированные) и исправлять замечания!
Этап 2. Асинхронный сервер (soft deadline 2024-02-29 18:29:59 MSK, hard deadline 2024-03-06 23:59:59 MSK)
Вынесите обработку запросов в отдельный ExecutorService
с ограниченной очередью, чтобы разгрузить SelectorThread
ы HTTP сервера. Подумайте о параметрах ExecutorService
(тип и размер очереди, количество потоков, обработка переполнений очереди и ошибок при обработке запросов) -- результаты всех экспериментов опишите в отчёте. Проанализируйте, стало ли лучше, чем раньше?
Проведите нагрузочное тестирование с помощью wrk2 с большим количеством соединений (не меньше 64) PUT
и GET
запросами.
Отпрофилируйте приложение (CPU, alloc и lock) под PUT
и GET
нагрузкой с помощью async-profiler.
Когда всё будет готово, присылайте pull request с изменениями, результатами нагрузочного тестирования и профилирования, а также анализом результатов по сравнению с предыдущей (синхронной) версией. На всех этапах оценивается и код, и анализ (отчёт) -- без анализа полученных результатов работа оценивается минимальным количеством баллов. Не забывайте отвечать на комментарии в PR (в том числе автоматизированные) и исправлять замечания!
Реализуем горизонтальное масштабирование через поддержку кластерных конфигураций, состоящих из нескольких узлов, взаимодействующих друг с другом через реализованный HTTP API.
Для этого в ServiceConfig
передаётся статическая "топология", представленная в виде множества координат всех узлов кластера в формате http://<host>:<port>
.
Кластер распределяет ключи между узлами детерминированным образом. В кластере хранится только одна копия данных. Нода, получившая запрос, проксирует его на узел, отвечающий за обслуживание соответствующего ключа. Таким образом, общая ёмкость кластера равна суммарной ёмкости входящих в него узлов.
Реализуйте один из алгоритмов распределения данных между узлами, например, consistent hashing, rendezvous hashing или что-то другое по согласованию с преподавателем.
Когда всё будет готово, присылайте pull request с изменениями, результатами нагрузочного тестирования и профилирования, а также анализом результатов по сравнению с предыдущей (нераспределённой) версией. На всех этапах оценивается и код, и анализ (отчёт) -- без анализа полученных результатов работа оценивается минимальным количеством баллов. Не забывайте отвечать на комментарии в PR (в том числе автоматизированные) и исправлять замечания! С учётом шардирования набор тестов расширяется, поэтому не забывайте подмёрдживать upstream.