Сеть

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

Отделите сбои на участке прокси от сбоев назначения, составьте план одобренных маршрутов с ограниченными повторами и записывайте смену маршрута как новую привязку.

Документация

Нужна структурированная документация по теме Сеть?

Эта статья относится к редакционной библиотеке. Для пошаговой настройки, справки и постоянных обновлений переходите сразу в соответствующий раздел docs.

Почему отказавший маршрут не равен непрерывному сеансу

Сеанс браузера, который идёт через прокси, зависит от двух звеньев, способных отказывать независимо: маршрута до прокси и назначения за ним. Когда отказывает маршрут, оператору веб-сервиса нужны три ответа. Что пользователь всё ещё видит? Что можно безопасно повторить? Считается ли переход на другой одобренный маршрут тем же сеансом? Короткий ответ: переключение может восстановить работу сервиса, но не заставляет страницу, её запросы в процессе выполнения и состояние приложения продолжаться без изменений, а смена маршрута выхода является новой сетевой привязкой, которая должна попасть в журнал.

В браузерах уже есть стандартное резервное поведение. Файл автоматической настройки прокси может вернуть упорядоченный список маршрутов, и браузер пробует следующую запись после сбоя соединения. Руководство MDN по PAC-файлам описывает формат списка, а документация Chromium по прокси описывает, как этот список обрабатывается. Такое поведение выбирает, куда пойдёт следующее соединение. Оно ничего не говорит о том, переживёт ли смену загружавшаяся страница, наполовину отправленная форма или воспроизводимый поток. Разделение этих двух вопросов лежит в основе хорошего плана переключения.

Схема: контекст браузера, упорядоченный список одобренных маршрутов, участок прокси и участок назначения с раздельными категориями сбоев, а также записанная смена маршрута, которая заканчивается новой привязкой или состоянием недоступности

Три термина помогают сохранить точность дальнейшего разбора. Маршрут это одобренный путь, по которому контекст браузера достигает назначений, включая точку входа прокси и учётную запись за ней. Категория сбоя называет, какой участок пути отказал и кто отвечает за следующее действие. Утверждение о непрерывности описывает, что пользователь видит потом: страница завершается, ограниченный повтор удаётся, появляется чётко обозначенное состояние недоступности или новая привязка маршрута начинает новый сценарий. Прокси на уровне контекста объясняет, как маршрут закрепляется за контекстом. Переключение начинается после того, как такая привязка уже есть, и отвечает на вопрос, что происходит, когда назначенный маршрут перестаёт работать.

Здесь речь идёт о разрешённой работе по одобренным маршрутам. Сбой никогда не даёт права на тихое прямое соединение или неодобренный маршрут, и ничто в этих рекомендациях не описывает, как менять провайдеров, чтобы скрыть активность, или как избегать решений назначения о доступе. Цель в том, чтобы поведение было предсказуемым для пользователя, а журнал оператора точным.

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

Запрос через HTTP-прокси проходит минимум два участка: от клиента до прокси и от прокси до назначения. RFC 9110 определяет коды состояния, которые сообщают о проблеме на втором участке, когда задействован прокси или шлюз. Код 502 Bad Gateway означает, что прокси получил некорректный ответ от сервера, к которому обратился, а код 504 Gateway Timeout означает, что он не получил от этого сервера ответ вовремя. Справка MDN по 502 объясняет ту же роль шлюза. Эти коды приходят от прокси и описывают его сторону, обращённую к назначению. Это не прикладные ошибки самого назначения.

Сбои до завершения участка прокси выглядят иначе. Отказ в соединении с точкой входа прокси, неудачное DNS-разрешение имени прокси или тайм-аут при подключении происходят раньше, чем какой-либо запрос доходит до назначения. Для HTTPS браузер сначала просит прокси открыть туннель методом CONNECT и начинает TLS-обмен с назначением только после того, как прокси ответит успешным статусом. Прокси, который отказывает в туннеле, отвечает 407 Proxy Authentication Required или возвращает статус шлюза на этом этапе, нарушил работу своего участка, хотя к назначению никто не обращался. Руководство MDN по прокси-серверам и туннелированию описывает этот туннель.

Сбои назначения образуют отдельную категорию. Когда туннель открыт, прикладная ошибка, ошибка сертификата или отказ на уровне приложения относятся к назначению и его владельцу. Код 503 может прийти с любой из сторон, поэтому выясните, кто его отправил, прежде чем кого-то назначать ответственным. Повтор ошибки назначения через другой маршрут редко помогает и может повторить действие, которое назначение уже обработало. Хорошая категория инцидента называет участок, наблюдаемый статус или ошибку и ответственного: поддержку провайдера для сбоев на участке прокси и владельца приложения для сбоев назначения.

Для каждой категории заранее запишите, что увидит пользователь. Если в открытии туннеля отказано, страница не загружается, и пользователь видит ошибку соединения или состояние недоступности приложения. Если навигация получает от прокси 502 или 504, пользователь видит страницу с ошибкой, а более поздняя попытка может удаться. Если подчинённый ресурс не укладывается во время ожидания, страница отображается частично, с недостающими изображениями или функцией, которая не запускается. Если назначение возвращает прикладную ошибку, пользователь видит собственное сообщение приложения. Когда эти исходы названы, поддержка может объяснить случившееся, не разбирая трафик.

Резервное переключение на уровне браузера реагирует на узкий набор событий. В документации Chromium сказано, что обычно право на переход к следующему прокси дают только сбои на уровне соединения, например неудачное разрешение DNS-имени прокси или неудачное подключение сокета к нему, и что сбои при установке туннеля CONNECT перестали считаться такими триггерами начиная с версии 67. Поэтому прокси, ответивший 502, сам по себе не заставляет браузер пробовать следующую запись списка. Оператор, который рассчитывает на использование следующего маршрута после ошибки шлюза, полагается на поведение, которого браузер не обеспечивает.

В той же документации отмечено, что у резервного переключения нет параметров настройки, а прокси, помеченный как неисправный, на некоторое время переносится в конец списка, а не удаляется. Поэтому порядок попыток может отличаться от записанного. Фиксируйте порядок, который вы наблюдаете при проверочном прогоне, а не считайте верным записанный.

Что пользователь всё ещё видит и что можно безопасно повторить

Когда маршрут отказывает посреди сценария, о странице перед пользователем верны три вещи. Уже отображённое содержимое остаётся на экране, потому что оно находится в странице, а не в маршруте. Запросы, выполнявшиеся в этот момент, заканчиваются ошибкой или тайм-аутом, и страница сама решает, как это показать. Ещё не отправленные запросы пойдут по тому маршруту, который будет действовать к их началу. Поэтому после переключения страница оказывается отчасти старой, отчасти новой, и приложение должно прямо определить, каким частям оно доверяет.

Отображённое содержимое не доказывает завершения операции. Форма, которая осталась на экране после тайм-аута, могла быть получена, а могла и не быть, а индикатор загрузки, который так и не завершается, ничего не сообщает пользователю. Дайте каждому шагу сценария признак завершения, видимый и пользователю, и оператору: сообщение о подтверждении, идентификатор запроса, который вернул сервер, или смену состояния на странице статуса. Без такого признака самое безопасное допущение после тайм-аута запроса, меняющего состояние, состоит в том, что его результат неизвестен.

Идемпотентность определяет, что можно повторять. Статья глоссария MDN определяет идемпотентный метод как такой, для которого один или несколько одинаковых запросов дают один и тот же задуманный эффект на сервере. RFC 9110 относит к идемпотентным PUT, DELETE и безопасные методы, например GET и HEAD, а POST к ним не относится. Стандарт разрешает клиенту автоматически повторять идемпотентный запрос после сбоя соединения, до получения ответа. Он же указывает, что клиенту не следует автоматически повторять неидемпотентный запрос, если у него нет способа узнать, что семантика запроса на самом деле идемпотентна, или способа обнаружить, что исходный запрос так и не был применён.

Эти определения описывают договор метода, а не то, что делает конкретное приложение. Точка входа GET, меняющая состояние, нарушает договор, а POST с ключом, который проверяет сервер, может быть безопасен для повтора. Отметьте каждую операцию сценария как повторяемую, повторяемую только с проверяемым сервером ключом или не повторяемую без подтверждения пользователя. Браузер не может по тайм-ауту понять, подействовало ли уже неидемпотентное действие, поэтому повтор платежа, сообщения или изменения учётной записи должен либо спросить пользователя, либо сначала проверить статус.

Идемпотентный не значит бесплатный. Повтор чтения по другому маршруту может вернуть другую региональную версию страницы, другую кэшированную копию или другое состояние ограничения частоты, а назначение может посчитать повтор дополнительной нагрузкой. Держите повторы редкими и ограниченными, как описано в следующем разделе, и не делайте повтор тихим, если разница важна для пользователя.

Аутентификация требует такого же внимания. Cookie сеанса, установленный назначением, принадлежит контексту браузера, а не маршруту, поэтому обычно сохраняется после смены маршрута. Тем не менее назначение может попросить пользователя подтвердить вход после смены сетевого расположения. Считайте такое подтверждение обычным исходом и не стройте сценарий в расчёте на то, что его не будет. Не записывайте учётные данные прокси в журналы сбоев; о том, как с ними обращаться, рассказывает материал аутентификация прокси в браузере и гигиена учётных данных.

План упорядоченных маршрутов и ограниченный бюджет повторов

План переключения это короткий документ из четырёх частей: упорядоченный список одобренных маршрутов, категории сбоев, при которых разрешён переход к следующему маршруту, бюджет повторов для каждого маршрута и конечное состояние, когда список исчерпан. Составьте его до инцидента и храните у владельца маршрута, потому что контакт провайдера, сетевой владелец и владелец приложения держат каждый свою часть.

Включайте только маршруты, одобренные для данной нагрузки, региона и категории назначения, в том порядке, в котором их нужно пробовать. Второй маршрут требует того же одобрения, что и первый, включая разрешение на цель и обращение с данными. Маршрут, который оказался доступным, не становится одобренной альтернативой. Если план выражен PAC-файлом или списком прокси в браузере, читайте список как техническую форму плана: каждая запись это маршрут, который план принимает. Прямая запись в таком списке означает решение выйти за границу прокси. Документация Chromium также сообщает, что при невозможности получить PAC-файл разрешение может вернуться к следующему варианту, часто к молчаливому прямому соединению, если скрипт не помечен как обязательный, поэтому проверьте, что делает ваша конфигурация в этом случае.

Дайте каждому маршруту небольшое фиксированное число попыток и ограничение по времени на весь сценарий и запишите оба значения как параметры политики, которые выбирает команда. Эти значения относятся к владельцу приложения, потому что читаемый документ, шаг оплаты и фоновая синхронизация допускают разное ожидание. Разносите попытки по времени, чтобы восстанавливающийся провайдер не получал шквал повторных запросов, и автоматически повторяйте только операции, отмеченные как повторяемые. Неповторяемые операции идут по пути подтверждения пользователем, описанному выше.

Заранее решите, какие сбои разрешают смену маршрута. Переход к следующему маршруту разумен, когда сбой относится к участку прокси: точка входа недоступна, туннель отклонён или прокси неоднократно возвращает статусы шлюза для разных назначений. Он неразумен, когда сбой относится к назначению. Он неразумен и тогда, когда прокси отклоняет учётные данные, поскольку код 407 указывает на проблему учётной записи, которую другой маршрут не исправит и которую должен решить провайдер. Решение назначения о доступе это решение, а не сбой, который нужно обходить другим маршрутом, и смена маршрута в ответ на него выходит за рамки одобренного использования.

Пока выполняется план, показывайте пользователю честный ход событий. Сообщение вроде «переподключение» точно, пока остаются попытки, а сообщение о недоступности точно, когда бюджет исчерпан. Бесконечный цикл не даёт пользователю ни того, ни другого. Если несколько контекстов браузера используют один маршрут, сбой затрагивает каждый из них, поэтому применяйте план к каждому контексту отдельно и ведите журнал тоже по контекстам.

Смена маршрута и состояния недоступности

Смена маршрута меняет выход, который видит назначение. Это новая привязка маршрута, а не продолжение прежней. Запишите её с идентификатором контекста, названием прежнего маршрута, названием нового маршрута, временем, категорией причины и тем, кто её одобрил. Назначение наблюдает новый сетевой источник и вправе считать последующие запросы пришедшими из другого места, поэтому всё, что зависело от прежнего источника, например региональная страница, состояние ограничения частоты или подтверждение входа, следует считать возможно изменившимся. Такая запись позволяет поддержке объяснить, почему пользователь увидел новый запрос, а проверке релиза сравнить сценарии до и после смены.

Не представляйте результат как один непрерывный сеанс. В отчётах и заметках поддержки обозначайте отрезок до смены и отрезок после неё как отдельные привязки маршрута внутри одного контекста браузера. Cookie и хранилище живут вместе с контекстом, поэтому состояние приложения может сохраниться, пока сетевой источник изменился. Оба факта принадлежат журналу, потому что непрерывность данных и непрерывность маршрута независимы. Объяснение для пользователя должно говорить о случившемся обычными словами: соединение восстановлено по другому одобренному маршруту, и вас могут попросить подтвердить действие.

Запросы, начатые до смены, завершаются по старому маршруту или терпят неудачу, а запросы, начатые после, идут по новому, поэтому страница может сочетать ответы от обоих. Не отправляйте неидемпотентный запрос повторно только потому, что сменился маршрут. Применяйте те же правила, что и раньше: повторяйте лишь то, что отмечено как повторяемое, и прежде всего проверяйте статус.

Когда одобренного запасного маршрута нет, план заканчивается состоянием недоступности, и это конечное состояние задано явно. Оно сообщает, что сервис недоступен, называет, что пользователь может сделать дальше, например повторить позже или обратиться в поддержку, и записывает в журнал категорию сбоя и владельца маршрута. Оно не заканчивается неявным прямым соединением, неодобренным провайдером или тихим циклом. Страница, которая загрузилась по прямому соединению после отказа прокси, может выглядеть как успех, но она изменила сетевую границу без решения, может открыть назначению собственный адрес организации и нарушает условие, при котором сценарий был одобрен.

Продумайте состояние недоступности. Сохраняйте локально то, что ввёл пользователь, если приложение это позволяет, отключайте элементы управления, которые повторили бы неповторяемое действие, пока статус не подтверждён, и давайте ссылку на страницу статуса, если она есть. Текст о том, что сервис не удалось достичь по одобренному маршруту, полезнее общей ошибки, потому что подсказывает поддержке, к какому владельцу обращаться.

Возврат на основной маршрут после его восстановления это ещё одна смена маршрута, и действует тот же журнал. Избегайте переключений туда и обратно при коротких перебоях. Удерживайте маршрут на протяжении сценария и пересматривайте его на естественной границе, например при новой задаче или новом контексте браузера, чтобы у каждого отрезка в журнале было понятное начало и понятная причина.

Эксплуатационная проверка и место продукта

Прорепетируйте каждую категорию сбоя, прежде чем полагаться на план. Используйте назначение, которое вы контролируете, тестовый маршрут, отклоняющий соединения, тестовый прокси, возвращающий статус шлюза, и точку входа назначения, возвращающую прикладную ошибку. Запишите, что увидел пользователь при каждой репетиции, и ответственного, которого называет журнал. Не репетируйте на сторонних назначениях так, чтобы это нагружало их или было для них неожиданным.

Повторяйте репетицию после смены тарифа провайдера, переноса точки входа, смены региона, крупного обновления браузера или существенного изменения назначения. Держите последний принятый план доступным, пока оцениваете кандидата, и сравнивайте один и тот же сценарий в обоих. Критерии приёмки это исход для пользователя, ограниченный сбой и ответственный за восстановление, а не метка протокола.

Обычно этим планом пользуются несколько команд. Провайдер отвечает за доступность маршрутов, сетевой владелец квалифицирует маршруты и их порядок, владелец приложения решает, какие операции повторяемы и что сообщает состояние недоступности, а владелец контекста применяет назначенный маршрут и ведёт журнал. Короткая передача дел между этими владельцами это более сильное свидетельство, чем одна строка журнала, и она оставляет учётные данные и подробный трафик в контролируемых системах, которые их уже защищают.

BotBrowser документирует привязку прокси к каждому контексту и переключение прокси во время работы командой CDP для существующего контекста браузера (ENT Tier3): запросы, уже выполняющиеся, завершаются через прежний прокси, а новые используют обновлённый, так что оператор может применить контролируемую и записанную смену маршрута. BotBrowser не документирует автоматическую проверку состояния прокси или автоматическое переключение, не может переносить запросы, выполняющиеся в момент смены, и гарантировать непрерывность страницы при смене маршрута, а также не может починить неисправный маршрут провайдера.

На практике считайте команду переключения шагом, который разрешает план, а не циклом восстановления. Документация BotBrowser советует дожидаться завершения каждой команды, прежде чем отправлять следующее изменение для того же контекста или начинать навигацию, зависящую от нового маршрута, и сообщает, что команда заново определяет адрес выхода, если только он не передан вместе с командой, и обновляет часовой пояс, региональные параметры и язык этого контекста. Запишите эти изменения в запись о маршруте вместе с новым маршрутом, потому что они входят в то, что видит назначение после смены. Динамическое переключение прокси описывает команду подробнее, а семантика HTTP-прокси и запросы браузера объясняет, как браузеры используют туннели CONNECT и ответы прокси.

Выполните проверки переключения

Примените эти проверки к репетиции в тестовой среде и запишите для каждой, пройдена она или нет.

  1. Прорепетируйте отклонённый туннель, статус шлюза от прокси, тайм-аут подключения и прикладную ошибку назначения. Пройдено, если журнал относит каждый случай к сбою участка прокси или назначения, называет ответственного и указывает, что увидел пользователь. Не пройдено, если какой-либо случай записан только как общая ошибка страницы.
  2. Выполните один случай, где прокси возвращает статус шлюза, и один, где назначение возвращает прикладную ошибку для той же страницы. Пройдено, если они отображаются как отдельные результаты с разными ответственными. Не пройдено, если они слиты в один счётчик сбоев.
  3. Сравните записанный план с настроенным списком маршрутов. Пройдено, если упорядоченные маршруты совпадают с одобренными, бюджет повторов и ограничение по времени на сценарий записаны, а прямой записи или неодобренного маршрута нет. Не пройдено, если в конфигурации есть запись, которой нет в плане.
  4. Во время отрепетированного тайм-аута отнесите каждую операцию сценария к повторяемым, повторяемым только с проверяемым сервером ключом или неповторяемым без подтверждения. Пройдено, если автоматически повторялись только повторяемые операции. Не пройдено, если неидемпотентный запрос отправлен повторно без ключа и без подтверждения пользователя.
  5. Запустите контролируемое переключение на следующий одобренный маршрут. Пройдено, если журнал показывает контекст, прежний маршрут, новый маршрут, время, категорию причины и утвердившего как новую привязку маршрута. Не пройдено, если в отчёте оба отрезка представлены как один непрерывный сеанс.
  6. Отключите запасной маршрут и повторите сбой. Пройдено, если сценарий заканчивается состоянием недоступности с записанными категорией сбоя и владельцем маршрута, а сетевой журнал не показывает соединений вне одобренного маршрута. Не пройдено, если страница загрузилась по прямому соединению или попытки продолжаются без конца.

Источники

#прокси#сеть#по контекстам#продакшен

Переведите BotBrowser из исследований в продакшн

Используйте эти руководства, чтобы понять модель, а затем перейти к кроссплатформенной валидации, изолированным контекстам и масштабируемому браузерному развертыванию.