2020 年,单点故障是稳定性的最大敌人
2020 年我们引入了智能负载均衡与故障自动切换。单点故障是代理服务不稳定的首要原因,高可用架构才是解决之道。
这一年发生了什么
2020 年,代理行业的需求在快速增长。用户对稳定性的要求从"不要经常断"变成了"最好永远不断"。但很多服务商还在用单机或少量节点支撑业务——一台机器挂了,一批用户就掉线。
这一年我们的技术重心放在一件事上:消灭单点故障。
为什么单点故障在 2020 年变得尤其重要
2020 年有一个特殊背景——疫情导致远程办公和线上业务激增。用户对代理服务的依赖度更高了,同时对服务中断的容忍度更低了。一个不稳定的代理服务,可能直接影响企业的远程办公效率和数据采集业务的连续性。
同时,代理行业自身也在快速变化。用户量增长了,流量增长了,对服务稳定性的要求也更高了。在用户量少的阶段,偶尔的故障可以通过人工处理和道歉来弥补。但当用户规模达到一定程度后,每一次故障都会影响大量用户,人工处理已经来不及。
这就是 2020 年我们全力投入高可用改造的直接原因。不是因为我们突然对稳定性有了新的认识,而是用户的规模已经达到了不做高可用改造就无法维持服务水平的临界点。
另外值得一提的是,2020 年初的疫情对代理行业产生了意想不到的推动作用。远程办公全面普及,企业对 VPN 和代理服务的需求大幅增长——有的用户用来访问海外办公系统,有的用来采集疫情相关数据,有的用来维护跨境电商店铺。仅第一季度,我们的新用户注册量就比 2019 年同期增长了近一倍。用户量快速增长的背后是更大的稳定性压力:服务的用户越多,单点故障的影响面就越广。这也让我们更加确信,高可用改造不是"锦上添花",而是"雪中送炭"。
高可用架构的基本原理
在深入展开之前,有必要先介绍一下高可用架构的核心理念:系统可用性 = MTBF / (MTBF + MTTR),其中 MTBF 是平均无故障时间,MTTR 是平均恢复时间。
这个公式告诉我们两个道理:
第一,要提高可用性,要么延长无故障运行时间(MTBF),要么缩短故障恢复时间(MTTR)。
第二,对于代理服务来说,MTTR 对用户感知的影响比 MTBF 更大。一个偶尔出故障但能在几秒钟内恢复的服务,用户可能完全感知不到。而一个很少出故障但每次出故障都要修几个小时的服务,用户每次都会注意到。
2020 年我们的策略是:在不显著降低 MTBF 的前提下,将 MTTR 从分钟级降低到秒级。这就是为什么我们全力投入自动切换——因为人工处理的时间单位是分钟,而自动切换的时间单位是秒。
什么是单点故障
单点故障(Single Point of Failure, SPOF)指的是系统中某个组件如果失效,会导致整个系统不可用的情况。在代理服务中,单点故障的表现形式多种多样:
- 某台代理服务器因为硬件故障宕机——如果你只有这一台服务器,所有用户都受影响
- 某个上游资源池因为 API 限流无响应——如果你只接了一个上游,所有依赖这个上游的用户都掉线
- 某个网络出口因为运营商问题断连——如果你只有这个出口,整个服务中断
- DNS 解析因为缓存污染失效——如果你依赖的 DNS 服务出问题,用户无法解析代理地址
每一种单点故障,在非冗余架构下都意味着服务中断。解决思路只有一个:不要有任何"唯一"的依赖。
多地域部署的实际拓扑
2020 年的高可用架构不仅仅是在同一机房内做冗余,还把节点分散到了多个地理区域。这种多地域部署的拓扑结构是保证可用率的关键。
我们的部署策略是按层分布的。核心层部署在华东和华北两个数据中心,承载用户认证、IP 资源调度、流量计费等核心服务,两个数据中心实时互备,任何一个数据中心整体故障时,另一个可以在 30 秒内接管全部流量。
代理层则部署在更多的地域节点上——除了华东和华北,还包括华南、西南以及香港地区。每个地域的代理节点组成一个独立的资源池,地域之间通过专线互联。当某个地域的网络出现波动时,流量可以在地域之间灵活调度。
接入层采用了多入口设计。用户在配置代理时可以获得多个入口地址,这些地址解析到不同地域的负载均衡器。如果某个入口不可达,客户端可以自动切换到另一个入口。这种设计避免了"所有用户都走同一个入口"的单点风险。
这种多地域拓扑在 2020 年经历了多次真实故障的验证。最典型的一次是某云服务商的华东可用区因电力故障宕机——由于核心服务部署在华北备用数据中心,代理层可以切换到华南和西南的资源池,用户几乎没有感知到服务中断。
我们的高可用架构设计
2020 年,我们对代理架构进行了全面的高可用改造。改造的核心原则是:每一层都做冗余。
接入层。 在用户和代理服务器之间增加了负载均衡器。用户的请求先到达负载均衡,由负载均衡根据后端节点的健康状态和负载情况分发到不同的代理服务器。这样即使某台代理服务器宕机,负载均衡会自动将流量导向其他健康节点。
代理层。 代理服务器本身也做了冗余部署。每个区域部署了多台代理服务器节点,节点之间互相备份。当某个节点出现故障时,其他节点可以立即接管其流量。
资源层。 上游资源来源从单来源扩展到了多来源。每个来源之间有独立的资源池和接入链路。当一个来源出现问题时,系统自动切换到其他来源。
监控层。 所有节点的健康状态被持续监控,监控数据驱动负载均衡和自动切换决策。
负载均衡策略
2020 年我们采用的负载均衡策略经历了几个阶段的演进:
第一阶段:轮询。 最简单的负载均衡策略,请求按顺序依次分发到各个后端节点。实现简单,但不考虑节点的实际负载和健康状况。结果发现有些节点已经过载了,请求还在往它上面分发。
第二阶段:最少连接。 将请求分发到当前活跃连接数最少的节点。这个策略比轮询更智能,但它假设所有节点的处理能力相同。在实际环境中,不同节点的性能和配置可能不同。
第三阶段:加权最小连接。 结合节点的处理能力和当前负载进行加权分发。性能更好的节点分配更多的请求,负载高的节点分配更少的请求。这是我们最终采用的策略,也是效果最好的。
负载均衡权重的调优过程
加权最小连接策略确定后,权重值的设定成了下一个需要解决的问题。权重设得太保守,高性能节点被闲置;设得太激进,低性能节点可能被压垮。
我们的调优过程分为三步。第一步是根据节点的硬件配置(CPU 核心数、内存大小、网络带宽)给出初始权重。硬件配置相同的节点初始权重相同。第二步是运行一段时间后,根据实际观测到的负载数据调整权重。我们发现一些硬件配置相同的节点,实际处理能力差异可能达到 20%——因为操作系统配置、同一宿主机上的邻居负载、磁盘 IO 等因素都在起作用。第三步是引入动态权重调整机制,系统根据节点的实时响应时间和失败率自动微调权重。响应时间变长或失败率上升的节点,权重自动降低;恢复正常的节点,权重逐步回升。
动态权重调整上线后,节点间的负载标准差降低了约 40%,节点过载的情况基本消失。
故障自动切换机制
故障自动切换是高可用架构的关键能力。切换的速度直接决定了用户受影响的时间。
我们设计的自动切换机制分为三个层级:
第一级:单节点故障切换。 当某个代理节点连续多次健康检查失败时,系统自动将其标记为离线,不再向其分发新请求。已经建立的连接会正常完成或被迁移到其他节点。切换时间控制在 10 秒以内。
第二级:资源池故障切换。 当某个上游来源的可用率低于阈值时,系统自动将流量切换到其他备用的资源池。这个切换的影响更大,因为涉及一大批节点的同时切换。切换时间控制在 30 秒以内。
第三级:区域级故障切换。 当某个区域的整体网络出现问题时(比如某个城市的机房断电),系统自动将流量切换到其他区域的节点。这是最极端的情况,但也要有预案。
高可用架构的挑战
虽然高可用架构的概念听起来很简单——"多做冗余、自动切换"——但在实际实施中遇到了一些挑战:
状态同步问题。 当有多个代理节点同时运行时,它们之间需要共享状态信息。如果这些状态信息不同步,可能导致同一 IP 被分配给不同用户、或者负载均衡器的决策基于过时的数据。
流量平滑切换。 当系统从故障节点切换到健康节点时,如果切换过于激进,可能导致健康节点瞬间被大量涌入的流量压垮。我们采用了"缓慢启动"策略——新节点在切换之初只接受少量请求,然后逐步增加。
数据一致性。 核心数据保持强一致,运营数据允许最终一致。
健康检查机制
健康检查是故障切换的基础。如果健康检查不准确,自动切换就没有判断依据。
我们的健康检查系统由以下几个部分组成:
主动探测。 每 5 秒向每个节点发送一次探测请求,测量响应时间和成功率。如果连续 3 次探测失败,节点被标记为"疑似异常";如果连续 6 次失败,节点被标记为"故障"。
被动检测。 除了主动探测,系统还会分析用户的请求失败率。如果某个节点的用户请求失败率突然上升,即使主动探测显示正常,系统也会启动排查流程。因为有些故障只影响真实用户流量,不影响探测请求。
关联分析。 当多个节点同时出现异常时,系统会进行关联分析,判断是这些节点各自的局部问题,还是一个影响全局的问题(比如资源池或网络链路故障)。
健康检查机制在故障中暴露的问题
健康检查上线后并非一帆风顺。有两次典型的故障让我们对健康检查的设计做了重要调整。
第一次是"假阳性"问题。 某个区域的所有节点在凌晨三点同时被标记为故障,自动切换触发,流量被迁移到其他区域。但值班人员排查后发现,所有节点的服务本身运行正常,故障原因是监控系统所在的网络区域在凌晨进行了维护,导致主动探测请求全部超时。这次教训让我们意识到健康检查本身不能有单点——监控节点也需要冗余部署,且探测流量应经过多条独立的网络路径。
第二次是"探测与真实流量不一致"的问题。 某个节点主动探测一直正常(响应时间约 50ms,成功率 100%),但用户的请求失败率持续上升。排查后发现,该节点的上游资源对特定 User-Agent 或请求头有特殊处理,主动探测使用的固定请求通过了,但用户发送的真实请求被拦截了。这次教训让我们在主动探测之外增加了"流量镜像"方式——将一小部分真实用户流量复制一份用于质量分析,而不是只依赖模拟探测。
怎么判断代理稳不稳(四):有没有多节点冗余
2020 年,我们建议用户关注服务商的节点冗余策略:
- 代理服务是单节点还是多节点?
- 故障节点如何被发现?
- 故障发生后,流量如何切换到健康节点?
- 切换需要多久?秒级、分钟级还是小时级?
一个简单的测试方法:关掉其中一个代理节点,看你的业务是否还能正常运行。
高可用改造的效果
2020 年的高可用改造完成后,服务稳定性有了明显提升。几个关键指标的变化:
- 故障平均恢复时间从 2019 年的约 3-5 分钟降低到约 30 秒
- 因单点故障导致的服务中断次数从 2019 年的多次降低到接近零
- 用户可以感受到的"中断"基本消失——即使后端有节点在切换,前端也几乎没有感知
这一年我们的投入
2020 年完成的技术升级:
- 引入智能负载均衡,根据节点健康状态和负载动态分配流量
- 实现三级故障自动切换机制
- 架构整体升级为全冗余设计,所有关键链路无单点
- 健康检查间隔缩短到秒级
- 建立关联分析能力,区分局部故障和全局故障
实际运维中的故障案例
2020 年我们在高可用改造过程中经历了一些典型的故障,这些案例对我们理解单点故障很重要:
案例一:云服务商区域故障。 某云服务商的可用区因电力故障宕机,影响了我们部署在该区域的部分节点。由于我们已经做了跨区域的冗余部署,故障被自动切换到其他区域。用户几乎没有感知,只有监控系统记录了这次切换。如果是单区域部署,这次故障会导致大面积服务中断。
案例二:上游 API 限流。 某个上游资源来源因为流量增长触发了 API 限流机制,导致从该来源获取的代理节点大面积不可用。自动切换机制检测到该来源的可用率下降后,将流量切换到其他来源。之前如果只依赖这一个来源,这次限流会直接导致服务中断。
案例三:负载均衡器自身故障。 负载均衡器本身如果也是单点,那它就成为了新的单点故障。我们在设计时对负载均衡层也做了冗余——主备两台负载均衡器,主节点故障时备节点自动接管。负载均衡器的冗余经常被忽视,但非常重要。
这些案例说明了一个道理:在系统设计中,消除一个单点故障的同时,要警惕新的单点故障的出现。 比如你消除了服务器单点故障,但引入了负载均衡器,负载均衡器如果只有一个,它就成了新的单点。每一层都要做冗余,每一层都要考虑"如果这里出问题怎么办"。
单点故障的成本分析
在做高可用改造时,我们需要在投入和收益之间找到平衡。不是所有的单点都要消除,有些单点故障发生的概率很低、影响有限,投入大量资源去消除它可能不划算。
但在代理服务中,单点故障的成本计算方式比较特殊:
- 直接成本:服务中断导致的用户流失和退款
- 间接成本:用户信任度下降、品牌声誉受损
- 机会成本:用户因为一次中断转向了其他服务商
在 2020 年的竞品分析中,我们发现一些用户选择服务商的考虑因素排序是:稳定性 > 价格 > 功能 > 服务。稳定性排在第一位。这坚定了我们在高可用上的投入决心。
一个具体的成本计算案例
为了让团队更直观地理解高可用投入的价值,我们做了一个具体的计算。假设某企业用户每天通过代理发送 50 万次请求,每次请求的平均业务价值为 0.01 元。在 95% 可用率下,每天约 2.5 万次请求失败,直接损失约 250 元。但实际损失远不止于此:失败的请求导致下游业务流程中断,运维人员需要手动恢复,每次故障平均消耗 30 分钟的人力成本。加上用户满意度下降带来的续费风险,一次 30 分钟的故障实际综合成本可能超过 2000 元。
高可用改造的投入——负载均衡器、冗余节点、自动切换系统、7x24 监控——一次性投入约数十万元,每年运维成本约数万元。按照每年数十次故障(改造前水平)计算,一年的故障损失已经接近甚至超过改造投入。这还不包括"因一次严重故障流失了一个大客户"这种难以量化的损失。从投入产出比看,高可用改造不是成本,而是对业务连续性的保险。
故障切换的时间线
2020 年我们优化了故障切换的完整时间线,确保每个环节都有清晰的预期时间:
| 阶段 | 时间目标 | 说明 |
|---|---|---|
| 故障发生 | T+0 | 节点宕机或网络中断 |
| 故障检测 | T+5s | 健康检查连续 3 次失败 |
| 故障确认 | T+8s | 排除误报,确认非临时波动 |
| 切换决策 | T+10s | 系统自动决定切换策略 |
| 流量迁移 | T+20s | 新请求转发到健康节点 |
| 已有连接处理 | T+30s | 已有连接完成或重连 |
| 故障通知 | T+60s | 相关人员收到通知 |
这个时间线的基础是所有环节都是自动化的。任何需要人工参与的环节都会大幅延长恢复时间。
年度反思
2020 年我们在技术上做了很多工作,但最大的收获不在技术本身。而是在这一年里,团队形成了一种共识:稳定性是设计出来的,不是运维出来的。
这个共识的意思是:你不能期望运维团队在故障发生后快速处理来弥补架构的不足。真正有效的稳定性保障,是在系统设计阶段就把故障考虑进去——不仅要考虑正常情况下的运行,还要考虑异常情况下的容错和恢复。
2020 年的高可用改造完成了这个思路的第一步。后续每年都在这个基础上继续优化。
高可用系统的日常运维
高可用架构上线后,运维方式也随之发生了变化。在单机架构时代,运维主要关注"服务器是否在线"。在分布式高可用架构下,运维关注的是更复杂的系统状态:各区域的负载均衡是否均匀、节点间的流量分配是否合理、故障切换系统是否处于正常待命状态。
我们建立了一套"混沌演练"机制——定期模拟各种故障场景来验证系统的自愈能力。演练场景包括:关闭某台代理服务器、切断某个区域的网络、模拟上游资源池不可用。每次演练后,团队根据系统反应和恢复时间评估高可用架构的实际效果,并对发现的问题进行改进。这种"主动找茬"的运维方式,让系统在真实故障发生前就经历了多次"模拟考"。
给用户的一句话建议
判断一个代理服务稳不稳,先问这个问题:你们有多少个节点?如果一个节点挂了,会发生什么?能清晰回答这个问题的服务商,才算真正在意稳定性。如果一个服务商说"我们有冗余机制"但不能具体说清楚冗余的层级和切换的时间,那这种冗余可能只是写在宣传页上,没有在生产中真正跑通过。
需要企业代理方案?
我们可根据目标站点、并发规模与稳定性目标提供定制方案。