Комплексный Go фреймворк для реализации и тестирования алгоритмов ограничения скорости. Этот проект предоставляет примеры реализаций различных стратегий ограничения скорости вместе с клиент-серверными инструментами для валидации и бенчмаркинга.
Этот проект состоит из:
- Тестовый клиент: Отправляет запросы с настраиваемой скоростью
- Тестовый сервер: Работает как эхо-сервер
- Примеры алгоритмов: 4 различные реализации ограничения скорости
- Запустите сервер:
go run server/main.go -protocol tcp -port 8080- В другом терминале запустите клиент:
go run main.go -server localhost:8080 -rate 100 -duration 30s# Запуск TCP сервера с подробным логированием
go run server/main.go -protocol tcp -port 8080 -verbose
# Тест с высокой скоростью (1000 зап/с, 10 соединений)
go run main.go -rate 1000 -connections 10 -duration 60s
# Тест протокола UDP
go run server/main.go -protocol udp -port 9090
go run main.go -protocol udp -server localhost:9090 -rate 500.
├── main.go # Тестовый клиент
├── server/
│ └── main.go # Тестовый сервер
└── sample/
├── token_bucket/ # Реализация токен бакет
├── fixed_window/ # Реализация фиксированного окна
├── sliding_window/ # Реализация скользящего окна
└── concurrent/ # Потокобезопасная реализацияВысокопроизводительный клиент для тестирования ограничения скорости.
Возможности:
- Поддержка протоколов TCP/UDP
- Множественные параллельные соединения (только TCP)
- Настраиваемый размер сообщения
- Отображение статистики в реальном времени
Параметры командной строки:
-server string # Адрес сервера (по умолчанию "localhost:8080")
-protocol string # Протокол: tcp или udp (по умолчанию "tcp")
-rate int # Сообщений в секунду (по умолчанию 100)
-duration duration # Длительность теста (по умолчанию 10s)
-connections int # Параллельные соединения, только TCP (по умолчанию 1)
-size int # Размер сообщения в байтах (по умолчанию 64)Пример вывода:
Запуск тестового клиента ограничения скорости
Протокол: tcp
Сервер: localhost:8080
Скорость: 1000 сообщений/секунду
Длительность: 30s
Соединений: 10
Размер сообщения: 64 байта
--- Статистика теста ---
Длительность: 30s
Отправлено сообщений: 30000
Успешных сообщений: 29850
Неудачных сообщений: 150
Процент успеха: 99.50%
Фактическая скорость: 1000.00 сообщений/секундуПростой сервер, который возвращает полученные сообщения.
Возможности:
- Поддержка протоколов TCP/UDP
- Множественные одновременные клиентские соединения
- Отображение статистики каждые 5 секунд
- Корректное завершение (Ctrl+C)
Параметры командной строки:
-protocol string # Протокол: tcp или udp (по умолчанию "tcp")
-port int # Порт прослушивания (по умолчанию 8080)
-verbose # Включить подробное логированиеПример отображения статистики:
[15:30:45] Получено: 5023, Обработано: 5023, Ошибок: 0, Скорость: 1004.60 сообщ/с
[15:30:50] Получено: 10089, Обработано: 10089, Ошибок: 0, Скорость: 1013.20 сообщ/сВозможности:
- Позволяет пакетную обработку
- Поддерживает среднюю скорость, разрешая краткосрочные всплески
- Эффективное использование памяти
Пример использования:
limiter := NewTokenBucket(100, 10) // Ёмкость 100, пополнение 10/секунду
if limiter.Allow() {
// Обработать запрос
}Случаи использования:
- Ограничение скорости API
- Контроль пропускной способности сети
- Когда допустим пакетный трафик
Возможности:
- Простая реализация
- Минимальное использование памяти
- Проблемы на границах окна
Пример использования:
limiter := NewFixedWindowLimiter(1000, time.Minute) // 1000 запросов в минуту
if limiter.Allow() {
// Обработать запрос
}Случаи использования:
- Когда нужно простое ограничение скорости
- Производительность приоритетнее точности
Возможности:
- Более точное ограничение скорости
- Решает проблемы границ фиксированного окна
- Немного большее использование памяти
Пример использования:
limiter := NewSlidingWindowLimiter(100, time.Minute) // 100 запросов в минуту
if limiter.Allow() {
// Обработать запрос
}Случаи использования:
- Когда требуется точное ограничение скорости
- Важна справедливость
Возможности:
- Высокая производительность с атомарными операциями
- Поддержка распределённой среды
- Пример HTTP middleware
Использование HTTP Middleware:
// Ограничение скорости по пользователю
userLimiters := &UserRateLimiters{
limiters: make(map[string]*ConcurrentTokenBucket),
limit: 100, // 100 запросов/минуту на пользователя
}
mux := http.NewServeMux()
mux.HandleFunc("/api/", handler)
// Применить middleware
http.ListenAndServe(":8080", RateLimitMiddleware(userLimiters)(mux))Сравнение алгоритмов (справочные значения):
| Алгоритм | Пропускная способность | Использование памяти | Возможности |
|---|---|---|---|
| Токен бакет | Высокая | Низкое | Поддержка всплесков |
| Фиксированное окно | Самая высокая | Самое низкое | Простой |
| Скользящее окно | Средняя | Среднее | Точный |
| Параллельный | Высокая | Низкое | Оптимизирован для параллелизма |
# Тестирование ограничения скорости API сервера (1000 зап/с, 5 минут)
go run main.go -server api.example.com:443 -rate 1000 -duration 5m -connections 50# Тест постепенного увеличения нагрузки
for rate in 100 500 1000 2000 5000; do
echo "Тестирование скорости: $rate зап/с"
go run main.go -rate $rate -duration 1m
sleep 10
done# Измерение пропускной способности с большим размером сообщения
go run main.go -size 1024 -rate 1000 -protocol udp-
Ошибка "Too many open files"
# Увеличить лимит файловых дескрипторов ulimit -n 65536
-
Ошибки соединения при высоких скоростях
- Настройте параметр
-connections - Проверьте размеры буферов на стороне сервера
- Настройте параметр
-
Потеря UDP пакетов
- Уменьшите скорость или размер сообщения
- Настройте размер UDP буфера ядра
# Сборка клиента
go build -o rate-limit-client main.go
# Сборка сервера
go build -o rate-limit-server server/main.go# Запуск юнит тестов
go test ./...
# Запуск бенчмарков
go test -bench=. ./sample/...- Создайте новый пакет в директории
sample/ - Реализуйте интерфейс
RateLimiter:type RateLimiter interface { Allow() bool AllowN(n int) bool }
- Добавьте тесты и бенчмарки
Лицензия MIT
Pull request'ы приветствуются. Для крупных изменений, пожалуйста, сначала откройте issue для обсуждения того, что вы хотели бы изменить.