网络

代理故障切换与用户可见的连续性

区分代理段故障与目标站点故障,规划有序的已批准路由和有限重试,并把路由变更记录为新的分配。

文档中心

想直接进入 网络 文档吗?

这篇文章属于博客内容库。若你要步骤化配置、参考说明和持续更新,请直接进入对应 docs 分区。

为什么失败的路由不等于连续的会话

经过代理的浏览器会话依赖两个可能各自失败的环节:通往代理的路由,以及代理背后的目标站点。路由失败时,Web 运维人员需要三个答案。用户还能看到什么?哪些操作可以安全重复?切换到另一条已批准路由后,还算同一个会话吗?简短的回答是:故障切换可以恢复服务,但不会让页面、进行中的请求或应用状态原样延续,而出口路由的变化是一次新的网络分配,应当写入记录。

浏览器本身已有标准的备用行为。代理自动配置文件可以返回一份有序的路由列表,浏览器在连接失败后会尝试下一项。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 名称,或无法与代理建立套接字连接;并且从第 67 版起,建立 CONNECT 隧道时的失败不再被当作触发条件。因此,返回 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 从研究走向生产

先用这些指南理解模型,再进入跨平台验证、隔离上下文和面向规模化的浏览器部署。