Ballast: Adaptive Load Test фреймворк в Uber
В этой статье затронем каким образом построен фреймворк для адаптивных лоад тестов в Uber.
Архитектура Uber выросла до тысяч взаимозависимых микросервисов, и необходимо тестировать критически важные компоненты при максимальной нагрузке, чтобы проверить надежность сервисов. Точное нагрузочное тестирование позволяет Uber'у проверить, работает ли набор сервисов с максимальной нагрузкой и оптимальной эффективностью, сохраняя при этом надежность.
Uber разработали Ballast, Adaptive Load Test фреймворк, который использует захват трафика с помощью фильтра пакетов Berkeley (BPF) и реплаит трафик с помощью механизма PID-контроллера для настройки количества запросов в секунду (RPS) для каждого сервиса. Ballast устраняет трудоемкость написания, запуска и контроля нагрузочных тестов, улучшает покрытие нагрузочными тестами и выполняет непрерывное нагрузочное тестирование, предоставляя информацию о возможностях обслуживания и постоянно повышая безопасность деплоя.
Big picture
Высокоуровнево архитектура выглядит так:
Высокоуровнево Ballast состоит из 6 компонентов:
- Load Generator считывает фикстуру нагрузочного теста и перенаправляет его в сервис для выполнения нагрузочных тестов.
- Traffic Capture предоставляет платформе возможность захвата служебного трафика в режиме реального времени. Это используется для подготовки test fixture. Пользователи также могут вручную предоставить test fixture.
- Golden Signals предоставляет инфраструктуре возможность измерять золотые сигналы для продакшн сервисов, включая летенси, доступность, пропускную способность и использование ресурсов, таких как ЦП.
- PID Controller roportional–integral–derivative controller для генератора нагрузки RPS. Он получает фидбек от Golden signals и завершает цикл управления тестом.
- Scheduler предоставляет платформе возможность планировать нагрузочные тесты в зависимости от потребностей пользователя. Также доступна опция always-on для нагрузочных тестов.
- Ballast Watchdog следит за всеми текущими нагрузочными тестами и подписывается на критические оповещения, чтобы обеспечить безопасность каждого нагрузочного теста в случае непредвиденных проблем. Например, глобальная блокировка, перебои в обслуживании сервисов и т.д.
Load Generator
Генератор нагрузки по умолчанию для Ballast называется Shadower.
Shadower использует архитектуру координатор/воркер. Координатор отвечает за запрос всех нагрузочных тестов в запланированном состоянии и поиск подходящего воркера для их запуска.
Архитектура координатор/воркер выглядит следующим образом
Shadower Coordinator
Координатор — это общедоступный компонент, горизонтально масштабируемый. У любого координатора вы можете:
- Запланировать нагрузочный тест: планирование выполняется асинхронно, когда координатор постоянно проверяет нагрузочные тесты в запланированном состоянии и пытается найти подходящего исполнителя для их запуска.
- Обновить нагрузочный тест: любой координатор может получить этот запрос, но вызов перенаправляется лидеру.
- Остановить нагрузочный тест: это делается асинхронно; когда воркер отправляет heartbeat, координатор проверяет запущенные нагрузочные тесты и уведомляет, если какой-либо из них был остановлен.
- Закверить нагрузочный тест
- Получить список всех нагрузочных тестов
Shadower Worker
Worker отвечает за выполнение нагрузочных тестов. Он имеет следующие особенности:
- Управление квотами: для передачи состояния координатору используются heartbeats. Хотя состояние является асинхронным, если координатор считает, что у воркера есть квота для нагрузочного теста, вызов запуска нагрузочного теста является синхронным, в этот момент воркер может отклонить нагрузочный тест и предоставить обновленную квоту координатору.
- Чтение payloads из Kafka.
- Чтение payloads из хранилища.
- Request mirroring: если вы предоставляете несколько хостов, он может отправлять один и тот же запрос на каждый хост.
- Сохранение метрик в time-series базу данных.
Shadower Mapper
command-line tool который обеспечивает кодирование/декодирование для всех доступных кодировок, которые используются в Uber (JSON, Thrift и т. д.). Он имеет следующие особенности:
- Base64 output для получения JSON encoded байнари payload.
- Gzip compressed payloads.
- Method mapping: если endpoint
/v1/foobar
в payload, нужно смапить эндрпоинт сthrift/proto
.
Пример:
Мапиться в
Traffic Capture
Компонент Traffic Capture считывает пакеты с сети и собирает их в request payload. Он использует пакетный фильтр Беркли (BPF), предоставляемый пакетом pcap , для захвата специфического сервис пейлоада. BPF — это технология, используемая в некоторых компьютерных операционных системах для программ, которым необходимо анализировать сетевой трафик.
Он поддерживает 3 протокола: HTTP 1.1, HTTP 2.0 и TChannel . TChannel — это networking framing protocol, созданный в Uber для общего RPC, поддерживающий out-of-order респонсы с чрезвычайно высокой производительностью, позволяющий посредникам быстро принимать решения о переадресации.
Этот компонент может перехватывать пакеты для этих протоколов по сети, собирать их в запрос к сервису и быть готовым к чтению load generatorом.
Golden Signals
Этот компонент построен на основе платформы Uber Metrics — M3 и позволяет фреймворку получать 4 golden signals (latency, traffic, errors, и saturation) для сервиса под лоад тестом. Во время раннинга нагрузочного теста Ballast отслеживает работоспособность и доступность сервиса, вызывая Golden Signals.
PID Controller
После того, как балласт запустит load тест, PID controller высчитывает значение ошибки как разницу между желаемым и фактическим состоянием теста. Алгоритм просчета выглядит следующим образом:
Где:
- K p - пропорциональный коэффициент усиления, параметр настройки,
- K i – интегральный коэффициент усиления, параметр настройки,
- K d – коэффициент усиления по производной, параметр настройки,
- e(t) = r(t) – y(t) – ошибка ( r(t) – заданное значение (целевое состояние), а y(t) – значение обратной связи):
- t - время или мгновенное время (т.е. настоящее),
- τ - переменная интегрирования (принимает значения от момента времени 0 до настоящего времени t )
- r(t): service golden signals SLO, включая target CPU (например, 80%), request latency (например 600ms), error rate (например, 0.1%)
- y(t): измеренные golden signals сервиса в real-time
Ballast Data Flow
- Ballast фиксирует продакшн трафик или пользователи вручную подготавливают тестовые фикстуры.
- Пользователи настраивают план нагрузочного тестирования с именем целевого сервиса, датацентром, целевыми SLO, местоположением тестового устройства и т. д.
- Ballast запускает нагрузочный тест и отслеживает золотые сигналы сервиса, чтобы настроить целевую пропускную способность генератора нагрузки.
- Ballast останавливает нагрузочный тест и записывает результат нагрузочного теста, когда служба достигает целевых SLO (например, когда загрузка ЦП достигает 80%).
Пример Ballast load test управляемый PID controllerом
Shadower RPS быстро увеличивался в начале, но замедлялся, когда его загрузка ЦП приближалась к таргет CPU.
В каких случаях Uber'у помогает Ballast:
- Оценка пропускной способности в праздничные дни
- Resilient Rollout
- Балласт используется для тестирования load shedder используемого серверной частью Uber Eats.
- Production debugging