Поиск решения для тестирования поведения приложения при сетевых сбоях и ошибках
У меня есть приложение, которое соединено с сервером по websocket. И сервер, и приложение следят за состоянием соединения, приложение умеет реконнектиться при потере соединения. На клиенте используется ws v7.3.1.
При каком-то типе сетевого сбоя кто-то из пары сервер-клиент начинает вести себя не так, как ожидается (то ли на сервере не умирает старое соединение и при этом выполняется создание нового, то ли на клиенте одновременно начинают существовать 2 соединения).
Нужна программа или npm-пакет (или какой-то аддон к https-proxy-agent, socks-proxy-agent), через которую я бы пропустил трафик приложения и которая бы создавала бы разные типы сетевых сбоев (в идеале - от серий быстрых реконнектов и вплоть до смены внешнего ip-адреса). Или нужно пояснение какой подход применить, чтобы самому инициировать сетевые сбои и ошибки.
Ответы (3 шт):
netem (tc)
Попробуйте пакет netem. На странице проекта есть примеры использования. Есть deb-пакет.
Программа может:
- сетевые задержки
- потеря, дублирование, перестановка порядка пакетов
- повреждение пакетов
pumba
Инструмент для докер-контейнеров. Репо на GitHub.
- краш-тест - вырубает отдельные контейнеры
- эмуляция сетевых сбоев (на основе netem)
- стресс-тестирование: CPU, память, файловая система, io и прочее
saboteur
Страница проекта. Есть CLI-вариант управления, а также можно управлять по HTTP:
curl -X POST -d '{ "name": "packet-loss-to-app-server", "type": "PACKET_LOSS", "direction": "IN", "to_port": 8080, "probability": 0.2, "correlation": 25 }' http://192.168.2.11:6660/
Написана на питоне. Возможности:
- полная блокировка порта
- задержки
- потеря пакетов
dummynet (ipfw)
Домашняя страница с примерами использования. Собирается из сорцов.
Программа ограничивает скорость сети в разных режимах. Остальные возможности также схожи с предыдущими программами.
Армия обезьян
Simian Army состоит из трех "обезьян хаоса", которые ломают части работающей системы. Разработано Netflix. Может также пригодиться, но похоже что заточено под AWS.
Решение для macos:
Инструмент Network Link Conditioner можно найти в пакете “Additional Tools for Xcode”. Вы можете скачать его со страницы Загрузки для разработчиков Apple.
Включение Network Link Conditioner изменяет сетевую среду в масштабе всей системы в соответствии с выбранной конфигурацией, ограничивая пропускную способность uplink or download bandwidth, latency, and rate of packet loss.
Вы можете выбрать одну из следующих предустановок:
- 100% Loss
- 3G
- DSL
- EDGE
- High Latency DNS
- LTE
- Very Bad Network
- WiFi
- WiFi 802.11ac
… Или создайте свой собственный в соответствии с вашими требованиями.
Свободный перевод ответа от участника @Gaff и статьи Network Link Conditioner
Я вынес в отдельный ответ, как можно протестировать веб-сокеты на предмет отказоустойчивости по сценарию. Для этого есть npm пакет artillery. На странице пакета есть описание его возможностей.
Вот что особенно интересно:
- можно написать собственные сценарии поведения, в несколько шагов
- нагрузочное и функциональное тестирование
Как бы я это использовал:
- написал сценарий типичного подключения к ws и обмен типичными данными
- настроил на непрерывное выполнение этого сценария в несколько потоков (штатная возможность artillery) на протяжении минуты
- написал тест на nodejs (mocha или что-то посовременней), который бы асинхронно запускал
artillery run ..., и одновременно - сетевые сбои через одну из программ в моем первом ответе, напримерnetem. Также на одну минуту - сбор и анализ метрик, которые пишет artillery
Сценарий для тестирования можно написать по этому примеру из этой статьи
config:
target: "wss://socket.ohdear.app/app/2420b144fceaca7df5a5?protocol=7&client=js&version=4.3.1&flash=false"
phases:
- duration: 60 # Test for 60 seconds
arrivalRate: 10 # Every second, add 10 users
rampTo: 100 # And ramp it up to 100 users in total over the 60s period
name: "Ramping up the load"
- duration: 120 # Then resume the load test for 120s
arrivalRate: 100 # With those 100 users we ramped up to in the first phase
rampTo: 100 # And keep it steady at 100 users
name: "Pushing a constant load"
scenarios:
- engine: "ws"
flow:
- send: '{"event":"pusher:subscribe","data":{"channel":"public"}}' # Subscribe to the public channel
- think: 15 # Every connection will remain open for 15s

