「边缘计算」不是一项新发明,它建立在三十年前就存在的 BGP 路由协议之上。Anycast 让同一个 IP 同时存在于全球数百个 PoP,路由协议在网络层完成就近分流,绕开了 GeoDNS 的 TTL 缓存和解析器偏差问题。理解这套机制,才能看清 Cloudflare 在 IXP 密集布点与 Vercel 区域数据中心之间的取舍从何而来——以及为什么「离用户近」和「离数据库近」在大多数场景下是两个互相竞争的目标。
「边缘计算」这个词在过去几年被反复炒作,但它描述的物理现实非常简单:在离用户更近的地方运行代码。
真正的问题是:用户分布在全球各地,怎么让请求自动到达最近的服务器?
这个问题不是 Cloudflare 发明的,CDN 行业在 1990 年代末就在解决它,答案是 BGP Anycast。
最直觉的想法是用 DNS:根据用户的 IP 地址返回最近的服务器地址。
这个方案叫 GeoDNS,确实被广泛使用,但有几个根本性的限制:
TTL 延迟:DNS 响应有 TTL,客户端和递归解析器会缓存结果。即使把 TTL 设到 60 秒,故障发生后也要等缓存过期才能切换到备用服务器。
解析器位置偏差:GeoDNS 根据发起 DNS 查询的递归解析器 IP 来判断地理位置,而不是用户真实 IP。如果用户使用 8.8.8.8(Google Public DNS)或 1.1.1.1,解析器在别的大洲,地理判断就会出错。
无法感知网络质量:地理距离最近不等于网络路径最优。两点之间的物理距离可能只有 100 公里,但 BGP 路由绕了半个地球。GeoDNS 对此一无所知。
BGP Anycast 在网络层解决这些问题,绕开了 DNS 的固有限制。
理解 Anycast,需要先理解 BGP 的基本工作方式。
互联网由数万个自治系统(AS,Autonomous System)组成,每个 AS 是一个独立管理的网络(ISP、企业、云服务商等)。BGP(Border Gateway Protocol)是 AS 之间交换路由信息的协议:
Anycast 的核心思想:让多个物理位置不同的服务器宣告同一个 IP 前缀。
三个 PoP(Chen 注:Point of Presence,接入点。指 CDN 或云服务商在某个地理位置部署的网络节点,通常包含路由器、负载均衡器和计算/缓存服务器。) 宣告同一个 IP 前缀,互联网路由协议根据 AS-PATH 长度、Local Preference 等属性,自动把每个用户的流量送到网络拓扑距离最近的 PoP。这不需要任何应用层的感知,在 IP 层就完成了。
BGP 路由器在多条路径之间做选择,依次按以下属性排序(越靠前越优先):
AS-PATH 长度是最重要的可控因素:经过的 AS 越少,路径越短,通常也越快。CF 在全球 100+ 个 IXP(互联网交换节点)数千个网络互连点(IXP 及私有 peering)100+ 个 IXP(互联网交换节点)(Chen 注:100+ 是 2016 年 CF 庆祝加入第 100 个 IXP 时的数字([Cloudflare Blog, 2016-01-18](https://blog.cloudflare.com/think-global-peer-local-peer-with-cloudflare-at-100-internet-exchange-points/))。截至撰文时,CF 官网显示已有 13,000+ 个网络互连,覆盖 337 个城市([cloudflare.com/network](https://www.cloudflare.com/network/))。IXP 数量本身未单独披露,但规模已远超百量级。) 建立 peering,目的就是缩短用户流量到达 CF PoP 的 AS-PATH 长度,减少经过的中间 AS 数量。
一个常见的疑问:TCP 是面向连接的,如果一个 TCP 连接中途因为路由切换跑到了另一个 PoP,连接不就断了吗?
是的,这正是 Anycast 在 TCP 层的限制:一条 TCP 连接必须始终到达同一个 PoP。Anycast 保证了新连接会到达最优 PoP,但不保证已有连接不会因为路由抖动而漂移。
在实践中,BGP 路由表的变化是相对稳定的,短时间内不会频繁切换。单次 HTTP 请求的生命周期通常只有几百毫秒,这段时间内路由基本不变,所以 Anycast 对 HTTP 是安全的。
QUIC(HTTP/3 的底层协议)的连接迁移(Connection Migration)特性从协议层解决了这个问题:QUIC 连接用连接 ID 而不是 IP:Port 四元组标识,即使网络地址变化,连接依然有效。这是 QUIC 相比 TCP 的重要优势之一。
有了 Anycast,下一个问题是:PoP 应该建在哪里?
直觉答案是「覆盖人口密集地区」,但实际的选址逻辑更复杂。
IXP(Internet Exchange Point,互联网交换节点)是多个 AS 集中建立 BGP peering 的物理地点。在 IXP 建立 PoP 的优势是:可以用最短的 AS-PATH 连接到大量本地 ISP,用户流量不需要经过上游 transit 提供商就能到达你的 PoP。
CF 在 2024 年2023 年2024 年(Chen 注:实为 2023 年 6 月。参见 [Cloudflare Blog, 2023-06-19](https://blog.cloudflare.com/cloudflare-connected-in-over-300-cities/):「connected to over 12,000 Internet networks in over 300 cities around the world」。) 宣告覆盖 300+ 个城市,很大程度上是因为他们在大量 IXP 都有 peering——IXP 通常已经有机房和网络基础设施,CF 只需要放一台服务器接入本地交换网络。
Vercel 的 PoP 分布与 CF 截然不同——不是 300+ 个城市,而是约 20 个(Chen 注:截至 2026-03-05,Vercel 官方文档列出恰好 20 个计算区域(iad1、lhr1、hnd1 等),另有 126 个 PoP 负责流量接入。参见 [Vercel Docs: Global network and regions](https://vercel.com/docs/regions)。)区域数据中心。
这个选择是有意为之,反映了不同的产品定位:
CF Workers 的工作负载是轻量的边缘逻辑(请求改写、鉴权、A/B 测试),这类逻辑计算量小,可以在每个 PoP 的单台服务器上运行,适合密集的全球分布。
Vercel Functions 运行的是完整的 Node.js 应用(Next.js SSR(Chen 注:Server-Side Rendering,服务端渲染。每次请求时在服务器上动态生成 HTML,与静态生成(SSG)相对。SSR 页面无法在 CDN 长期缓存,每次都需要执行函数,因此对计算资源和数据库连接的要求比纯静态站点高得多。)、Server Actions),需要连接数据库、调用外部 API,这类工作负载需要更强的计算资源和更稳定的网络连接,更适合区域数据中心而不是边缘 PoP。
Vercel 把静态资源的分发(CDN 命中)和动态计算(Function 执行)分开处理:静态资源依然全球缓存,延迟低;动态请求路由到区域数据中心,与数据库在同区域,数据库访问延迟低。
这个设计的隐含假设是:大多数请求都应该命中 CDN 缓存(静态资源),动态请求是少数。对于 Next.js 应用(页面静态生成 + API 路由),这个假设通常成立。
一个 PoP 从流量入口到执行层,是一条完整的分层处理链路。
每一层的职责:
BGP 路由器:接收来自互联网的 BGP 连接,维护路由表,将到达本 PoP Anycast IP 的流量接收进来。通常是硬件路由器(Juniper/Cisco)或白盒交换机(运行 FRRouting 等开源实现)。
L4 负载均衡:使用 ECMP(Equal-Cost Multi-Path)将流量分散到多台 L7 服务器。ECMP 基于五元组(源 IP、源端口、目标 IP、目标端口、协议)做哈希,保证同一条 TCP 连接始终到达同一台 L7 服务器(保持连接一致性)。
L7 反向代理:TLS 终止(HTTPS 解密在此完成),HTTP 协议解析,根据请求路径、Host 头、缓存策略决定下一步:返回缓存、交给执行层、或回源。CF 使用自研的 Pingora(Chen 注:Pingora 是 CF 用 Rust 从头编写的反向代理框架,2022 年替换掉原有的 Nginx,每天处理超过一万亿次请求。主要动因是 Nginx 的 per-process 连接模型在 CF 规模下无法高效复用连接,而 Pingora 的多线程+连接池设计将连接复用率提升了约 87%。参见 [Cloudflare Blog, 2022-09-27](https://blog.cloudflare.com/how-we-built-pingora-the-proxy-that-connects-cloudflare-to-the-internet/)。)(Rust 实现),Vercel 使用 Nginx 变体Vercel 使用的内部反向代理实现未公开Vercel 使用 Nginx 变体(Chen 注:Vercel 官方从未公开其内部反向代理的具体实现,官方文档和技术博客只使用「gateway」「intelligent reverse proxy」等泛称。此处「Nginx 变体」说法来源不明,存疑。)。
缓存层:静态资源(JS/CSS/图片)缓存在本地,NVMe SSD 读取速度可以在微秒级返回。缓存键通常是 URL + 部分请求头的哈希。
执行层:动态请求到达这里,启动 isolate 或 microVM,运行函数代码。
用户浏览器与服务器的 TLS 握手(特别是首次连接)需要 1~2 个 RTT。如果 TLS 在源站终止,握手的延迟就是用户到源站的 RTT;如果在最近的边缘 PoP 终止,握手延迟就是用户到 PoP 的 RTT——通常缩短几十到几百毫秒。
这是 CDN/边缘网络对延迟的最直接贡献之一,与缓存命中率无关。
当一个 PoP 发生故障,流量需要自动切换到其他 PoP。BGP Anycast 的故障切换机制是撤回路由宣告。
BGP 故障切换有一个不可避免的延迟:BGP 收敛时间。BGP UPDATE 消息需要从故障 PoP 的邻居扩散到整个互联网路由表,这个过程通常需要 30 秒到 3 分钟(取决于网络规模和 BGP timer 配置)。
这意味着:PoP 故障后,仍会有 30 秒~3 分钟的流量被路由到故障节点(TCP 连接失败,用户看到错误)。
工程上的缓解手段:
理解了 BGP Anycast 和 PoP 架构,再看 CF 和 Vercel 的差异,就能看到本质。
CF 的 AS13335 是一个内容交付网络 + 边缘计算网络:
Vercel 的网络是CDN + 区域计算集群:
两种架构没有绝对优劣,只有场景匹配度:
本站的一次典型页面请求,路由路径如下:
大多数请求(页面、静态资源)在 CDN 层命中缓存,不经过 Function。只有评论 API 和阅读量统计需要到达 Function 层,再访问 Redis。
这个架构让网站的主要访问路径几乎没有计算成本——CDN 命中是纯 I/O,没有函数调用,也没有数据库访问。
专线 SaaS 没有公网 BGP,不能用 Anycast 路由。但同样的问题依然存在:你有多个数据中心,多个客户通过不同专线接入,如何设计流量路由?
BGP Anycast 的核心思想——在网络层解决路由,而不是在应用层——在专线环境里同样适用,只是协议换了。
用 OSPF/ISIS 替代 BGP:专线网络内部可以运行 OSPF 或 ISIS(链路状态路由协议),每个数据中心宣告相同的服务 IP(类似 Anycast),客户请求自动路由到拓扑距离最近的可用数据中心。故障切换比公网 BGP 更快(OSPF 收敛通常在秒级,配合 BFD 可到毫秒级)。
用 SDN 替代分布式路由:如果专线网络规模不大(几个数据中心),可以用 SDN 控制器(如 Cisco ACI、华为 iMaster NCE)集中管理路由策略,实现更精细的流量工程和故障切换,而不依赖分布式路由协议的自动收敛。
客户接入点即「边缘节点」:在专线 SaaS 里,「边缘」的语义变了——不是 CDN PoP,而是在客户专线接入处部署的接入层服务。这个接入层可以做:TLS 终止(与公网边缘 PoP 相同)、请求鉴权(验证客户身份)、流量整形(限速、优先级调度)、本地缓存(对于读多写少的数据,减少回中心数据中心的专线带宽消耗)。
专线带宽是硬约束:公网 CDN 可以无限扩展带宽(增加 PoP 即可),专线带宽是有限且昂贵的资源。这让本地缓存的价值远超公网场景——能在接入层命中缓存的请求,就不消耗专线带宽。架构设计时应优先思考:哪些数据可以在接入层缓存?缓存一致性如何保证?