Представляет собой HTTP-сервер, который принимает входящие запросы
и перенаправляет их на свободный и доступный Backend-сервер.
Адреса серверов должны быть заданы в Config-файле.
- Использует стандартный HTTP-пакет net/http
- Реализует ReverseProxy с использованием пакета net/http/httputil
- Использует Redis для хранения Rate Limits пользователей
- Проект использует чистую архитектуру (API, service и repository слои)
- В проекте реализован DI-контейнер (service_provider.go)
- Для взаимодействия с сервисами используются интерфейсы, что позволяет легко заменять их реализацию
а также упрощает процесс тестирования благодаря возможности генерации Mock-ов на основе интерфейсов
- Реализован алгоритм балансировки Round Robin - доступ к Backend-серверам осуществляется по круговой очереди
- Реализован Health Check - механизм, периодически проверяющий состояние каждого Backend-сервера
(интервал настраивается в Config-файле) - Rate limiting на основе алгоритма Token Bucket (дефолтная настройка происходит в Config-файле)
- Возможность установить кастомные Rate Limits конкретному пользователю через RestAPI
- Асинхронная обработка запросов с помощью использования паттерна Worker Pool (Хоть и сервер на net/http по дефолту асинхронный, для примера был реализован WorkerPool и применен в api/loadBalancer/check.go)
- Синхронизация работы в условиях конкурентных вызовов с помощью Mutex и Channels
- Graceful Shutdown реализованный с помощью кастомного модуля Closer
- REST API для получения добавления/удаления/изменения и получения информации состоянии Rate Limits пользователей
- Redis для хранения данных о Rate Limits пользователей
- Логирование информации о запросах и ошибках с использованием пакета slog
- Использует IP в качестве уникального идентификатора каждого пользователя
- Выделяет на каждый IP отдельный Bucket токенов
- Настройка Bucket - происходит через Config-файл
- Имеется возможность установить кастомный Config-файл конкретному клиенту (на уровне запуска приложения)
- Логирование информации о состоянии каждого клиента по IP (каждый тик)
- Атомарность операций с токенами
- Использование RWMutex для минимизирования блокировок, обеспечивающих атомарность
- Простая реализация сервера с двумя endpoints: "/" и "/health"
- Возможность запускать на разных портах благодаря указанию флага -port
- Много операций чтения и мало операций записи - Redis отлично подходит
- Приложение требует низкой задержки - Redis используется как кэш
- Данные не являются особо важными, в случае чего их легко восстановить
- В дальнейшем можно использовать TTL для автоматизированного и гибкого управления и хранения Rate Limits
- Method=GET /clients - Получить список всех пользователей и их RateLimits
- Method=POST /clients - Добавить пользователю кастомные RateLimits
- Method=GET /clients/{id} - Получить информацию о RateLimits конкретного пользователя
- Method=PUT /clients - Обновить данные RateLimits у пользователя
- Method=DELETE /clients/{id} - Удалить RateLimits пользователя (установятся дефолтные из Config-файла)
- Для Add и Update
{
"id": "127.0.0.1",
"capacity": 20,
"refill_rate": 2,
"interval": 2
}
Можно запустить двумя способами:
- Запустить локально
- Запустить через Docker
Пример настроенного Config-файла
loadBalancer:
host: "localhost"
port: "8080"
backends:
addresses:
- "http://localhost:9000"
- "http://localhost:9001"
- "http://localhost:9002"
healthChecker:
interval: 2
rateLimiter:
capacity: 10
refill_rate: 1
refill_interval: 5
workerPool:
pool_size: 5
queue_size: 5
Для запуска локально потребуется запустить отдельно Backend-сервера, Балансировщик нагрузки и redis базу данных
Для запуска нескольких серверов на разных портах, нужно установить значение флага -port на любой открытый порт
cd ./BackendServer
go mod tidy
go run cmd/main.go -port=9000Предлагается запустить Redis внутри Docker
docker-compose build redis
docker-compose up redis cd ./loadBalancer
go mod tidy
go run cmd/main.goЗапуск через докер требует установленного и запущенного docker в системе, а также docker-compose
docker-compose build
docker-compose upПри capacity = 100: пример 100% Complete Requests и быстрой скорости ответа
ab -n 100 -c 50 http://127.0.0.1:8080/При capacity = 100: пример 10% Complete Requests и быстрой скорости ответа
ab -n 1000 -c 100 http://127.0.0.1:8080/