Skip to content

Latest commit

 

History

History
308 lines (230 loc) · 11.6 KB

File metadata and controls

308 lines (230 loc) · 11.6 KB

Фреймворк для тестирования ограничения скорости

Комплексный Go фреймворк для реализации и тестирования алгоритмов ограничения скорости. Этот проект предоставляет примеры реализаций различных стратегий ограничения скорости вместе с клиент-серверными инструментами для валидации и бенчмаркинга.

Обзор

Этот проект состоит из:

  • Тестовый клиент: Отправляет запросы с настраиваемой скоростью
  • Тестовый сервер: Работает как эхо-сервер
  • Примеры алгоритмов: 4 различные реализации ограничения скорости

Быстрый старт

Базовое использование

  1. Запустите сервер:
go run server/main.go -protocol tcp -port 8080
  1. В другом терминале запустите клиент:
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/           # Потокобезопасная реализация

Детали компонентов

Тестовый клиент (main.go)

Высокопроизводительный клиент для тестирования ограничения скорости.

Возможности:

  • Поддержка протоколов 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 сообщений/секунду

Тестовый сервер (server/main.go)

Простой сервер, который возвращает полученные сообщения.

Возможности:

  • Поддержка протоколов 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 сообщ/с

Алгоритмы ограничения скорости

1. Токен бакет

Возможности:

  • Позволяет пакетную обработку
  • Поддерживает среднюю скорость, разрешая краткосрочные всплески
  • Эффективное использование памяти

Пример использования:

limiter := NewTokenBucket(100, 10) // Ёмкость 100, пополнение 10/секунду

if limiter.Allow() {
    // Обработать запрос
}

Случаи использования:

  • Ограничение скорости API
  • Контроль пропускной способности сети
  • Когда допустим пакетный трафик

2. Фиксированное окно

Возможности:

  • Простая реализация
  • Минимальное использование памяти
  • Проблемы на границах окна

Пример использования:

limiter := NewFixedWindowLimiter(1000, time.Minute) // 1000 запросов в минуту

if limiter.Allow() {
    // Обработать запрос
}

Случаи использования:

  • Когда нужно простое ограничение скорости
  • Производительность приоритетнее точности

3. Скользящее окно

Возможности:

  • Более точное ограничение скорости
  • Решает проблемы границ фиксированного окна
  • Немного большее использование памяти

Пример использования:

limiter := NewSlidingWindowLimiter(100, time.Minute) // 100 запросов в минуту

if limiter.Allow() {
    // Обработать запрос
}

Случаи использования:

  • Когда требуется точное ограничение скорости
  • Важна справедливость

4. Параллельная реализация

Возможности:

  • Высокая производительность с атомарными операциями
  • Поддержка распределённой среды
  • Пример 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))

Бенчмарки производительности

Сравнение алгоритмов (справочные значения):

Алгоритм Пропускная способность Использование памяти Возможности
Токен бакет Высокая Низкое Поддержка всплесков
Фиксированное окно Самая высокая Самое низкое Простой
Скользящее окно Средняя Среднее Точный
Параллельный Высокая Низкое Оптимизирован для параллелизма

Практические случаи использования

1. Тестирование ограничения скорости API сервера

# Тестирование ограничения скорости API сервера (1000 зап/с, 5 минут)
go run main.go -server api.example.com:443 -rate 1000 -duration 5m -connections 50

2. Сценарии нагрузочного тестирования

# Тест постепенного увеличения нагрузки
for rate in 100 500 1000 2000 5000; do
    echo "Тестирование скорости: $rate зап/с"
    go run main.go -rate $rate -duration 1m
    sleep 10
done

3. Измерение пропускной способности сети

# Измерение пропускной способности с большим размером сообщения
go run main.go -size 1024 -rate 1000 -protocol udp

Устранение неполадок

Распространённые проблемы

  1. Ошибка "Too many open files"

    # Увеличить лимит файловых дескрипторов
    ulimit -n 65536
  2. Ошибки соединения при высоких скоростях

    • Настройте параметр -connections
    • Проверьте размеры буферов на стороне сервера
  3. Потеря 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/...

Добавление новых алгоритмов

  1. Создайте новый пакет в директории sample/
  2. Реализуйте интерфейс RateLimiter:
    type RateLimiter interface {
        Allow() bool
        AllowN(n int) bool
    }
  3. Добавьте тесты и бенчмарки

Лицензия

Лицензия MIT

Вклад в проект

Pull request'ы приветствуются. Для крупных изменений, пожалуйста, сначала откройте issue для обсуждения того, что вы хотели бы изменить.

Ссылки