Тест переключения: выживает ли установленный поток TCP?
Резервный выход может принимать каждое новое соединение и всё же обрывать уже идущую передачу. Проверьте оба результата и оставьте случай возврата в плане.
Два результата скрыты во фразе «резерв работает». Новый запрос завершается успешно — это восстановление. Уже идущая передача продолжается — это непрерывность. Это разные обещания, и большинство схем переключения дают первое, а второе тихо заканчивается по тайм-ауту. Решите, какое нужно вам, прежде чем выбирать механизм, и напишите тест так, чтобы он мог их различить.
Два результата, которые выглядят как один успех
Представьте клиента с адресом 10.90.0.42 и соединением к 198.51.100.20:443. Основной выход преобразует это в один публичный адрес и порт, а резервный выход — в другой. Внутренний адрес клиента никогда не меняется, поэтому люди ожидают, что соединение выживет.
Сервер не видит внутренний адрес. Он видит преобразованную конечную точку, и после переключения эта точка другая.
Поэтому старый поток завершается по тайм-ауту, а новое соединение к тому же сервису работает сразу. Оба наблюдения верны одновременно.
Что видит сервер, когда выход меняется
TCP-соединение определяется своей четвёркой, и смена адреса или порта источника создаёт для принимающего хоста другое соединение. Пакеты, приходящие с нового источника по соединению, которого сервер не знает, отбрасываются или получают в ответ сброс. Ничто в адресе клиента VPN не сохраняет связь при таком изменении.
Переключение с сохранением состояния существует именно для того, чтобы этого избежать, и работает за счёт обмена состоянием преобразования и состоянием соединений между пересылающими устройствами. Это свойство пары, а не туннеля, и его нужно проектировать и проверять, а не предполагать.
Проверьте, действительно ли пара хранит состояние, прежде чем обещать кому-либо непрерывность. Команды ниже показывают текущее состояние с обеих сторон.
conntrack -L -d 198.51.100.20 2>/dev/null | head
ss -tin dst 198.51.100.20
tcpdump -ni any host 198.51.100.20 -c 10Почему одного и того же публичного адреса недостаточно
Сохранение одного публичного адреса на обоих путях — хорошее начало, потому что сервер тогда видит ту же исходную точку. Само по себе этого недостаточно. Пересылающему устройству по-прежнему нужны состояние преобразования, состояние межсетевого экрана и пригодный обратный путь, и всё это должно существовать на том устройстве, которое после переключения несёт трафик.
RFC 3022 описывает преобразование адресов и рассматривает обмен состоянием между преобразующими устройствами как часть резервной схемы. Плавающий адрес или скопированный профиль переносит конфигурацию, но не переносит состояние.
Поэтому тест, который только пингует через резерв, доказывает очень мало. У ping нет состояния соединения, которое можно потерять.
Решите, насколько жёстко требование
Если пользователи могут переподключиться после сбоя, схема является схемой восстановления, а приёмочный тест — это новый запрос. Если передача файла должна выжить, схеме нужны синхронизация состояния и гораздо более тщательный тест. Если должна выжить удалённая сессия, требование ещё жёстче и может потребовать механизма на уровне приложения, а не сети.
Запишите требование как предложение с измеримым результатом, например загрузка завершается без перезапуска или оператор переподключается в течение минуты. Затем выберите самый дешёвый механизм, который его удовлетворяет, и часто это схема восстановления.
Явно скажите, что происходит при возврате основного пути, потому что автоматический возврат может прервать соединение, которое только что восстановилось на резерве. Этот случай относится к плану тестирования, а не к сноске.
Проверьте старый поток и новый запрос
Запустите безобидную длительную передачу через основной путь, затем отдельный новый запрос к тому же сервису. Запишите контекст приложения, наблюдаемый адрес выхода и время. Разорвите основной путь одобренным способом и продолжайте наблюдать за исходной передачей, отправляя новый запрос через резерв.
Сообщите три значения: продолжился ли старый поток, был ли сброшен или завершился по тайм-ауту; когда новая операция впервые сработала; и прервал ли возврат что-либо. Эти три строки и есть протокол приёмки.
ss -tin dst 198.51.100.20
curl -sS -o /dev/null -w '%{http_code} %{time_total}\n' https://198.51.100.20/
tcpdump -ni any port 443 -c 20Если нагрузка записывает данные, не повторяйте неопределённую операцию вслепую после тайм-аута. Запись могла дойти до того, как ответ потерялся. Спросите результат у приложения или повторите только там, где операция идемпотентна. Затем запишите заявление о приёмке в трёх частях: новые операции восстанавливаются согласно политике выхода, существующие потоки имеют задокументированное поведение при прерывании, а приложение безопасно продолжает работу. Это заявление проверяемо и честно говорит о том, чего схема не обещает.