边缘计算与 CDN:把计算推近用户
用户在亚洲、服务器在美国,延迟 300ms?CDN 缓存静态资源、Edge Functions 在边缘跑逻辑,让请求就近处理。本文讲清 CDN 的缓存机制、Edge Functions(Cloudflare Workers/Vercel Edge)、何时该把逻辑从中心迁到边缘,以及边界(边缘有限制,不是什么都该推到边缘)。
本文要点
- 主题聚焦:Next.js、DevOps
- 适合人群:独立开发者、全栈工程师、AI 应用开发者
- 核心价值:快速理解背景、实践路径、常见误区和工程建议
边缘计算与 CDN:把计算推近用户
先讲一个让人沮丧的物理事实:光在光纤里跑,每秒大约 20 万公里。
这意味着一个亚洲用户请求一台美国服务器,数据单程跨越太平洋就要 60–100ms,往返 150–250ms 起步——这还只是物理传输,没算 TLS 握手、服务端处理、数据库查询。你优化了代码、加了索引、上了 Redis,结果 RTT 一旦超过 200ms,所有后端努力都被那根跨海光纤吃掉一半。
所以,过去十年前端性能工程的核心命题其实只有一句话:既然无法让光跑得更快,那就把内容和计算推到离用户更近的地方。
这就是 CDN 和 Edge Computing 的本质。本文把它们放在一起讲,因为它们是同一个思路在不同层面的落地——CDN 推"内容",Edge 推"计算"。
一、延迟的物理极限:为什么要"推近用户"
先建立一个心智模型。用户访问一个网页,延迟大致由四部分组成:
[用户] --(网络 RTT)--> [服务器] --(处理)--> [DB] --(回传)--> [用户]
↑ 物理延迟 ↑ 计算延迟 ↑ I/O 延迟
你能优化的只有后三段:计算延迟靠更好的代码和更快的运行时(V8、Rust、缓存);I/O 延迟靠索引、连接池、读副本;但网络 RTT靠的是地理位置——你没法把上海到法兰克福的物理距离缩短。
唯一能"作弊"的办法是:把服务器搬过来。
- 搬一份静态副本过来 → CDN
- 搬一段计算逻辑过来 → Edge Function
这两个方向构成了现代边缘架构的全部基础。
二、CDN:把静态资源缓存到世界每个角落
CDN(Content Delivery Network)做的事很朴素:在全球部署大量边缘节点(POP,Point of Presence),用户请求时按地理位置就近接入,如果节点上有缓存的资源就直接返回,没有才回源到中心服务器。
[中心源站] (你部署在 Vercel / 自建机房)
^
| 回源(未命中时)
v
[新加坡节点] [法兰克福节点] [美西节点] [圣保罗节点]
^ ^ ^ ^
| | | |
亚洲用户就近取 欧洲用户就近取 美洲用户就近取 南美用户就近取
CDN 真正的难点不在"缓存",而在缓存策略。三个核心概念:
1. 缓存键(Cache Key)。通常是 URL + Host + 部分 Header。带 ?v=123 的版本号、/api/user?id=5 的参数都会影响命中。一个常见坑:同一个图片带不同 ?token= 签名,导致每个用户各缓存一份——要么把签名从缓存键里排除,要么改用 Cookie 鉴权。
2. TTL(Time-To-Live)。资源在节点上存活多久。HTML 几十秒、带 hash 的 _next/static/chunk-abc.js 一年、API JSON 几秒或不缓存。Next.js 里 Cache-Control 头和 revalidate 时间本质上都是在管 TTL。
3. 失效(Invalidation)。CDN 圈最著名的名言是 Phil Karlton 那句:"只有两件难事,缓存失效和命名。"TTL 让缓存"自然过期",但内容更新时你需要主动踢掉旧版本。Cloudflare 的 Cache Tags、Fastly 的 Surrogate Keys、Vercel 的 revalidateTag 都是干这个的——给资源打标签,发布时按标签批量清除。
实战建议:带内容哈希的静态资源给不可变长缓存,HTML / API 走短 TTL + 主动失效。这是 Next.js App Router 默认帮你做的事——_next/static/* 永久缓存,页面按 revalidate 走 ISR。
三、Edge Functions:把计算也推到边缘
CDN 解决了静态资源,但动态请求(登录、下单、个性化推荐)怎么办?以前必须回源到中心服务器,于是又要跨海一次。
Edge Functions 的答案:把一段 JS/TS 逻辑部署到全球边缘节点,请求就近执行,只有真正需要中心数据时才回源。
三大主流玩家:
- Cloudflare Workers:基于 V8 isolate(不是容器,不是 VM),冷启动几乎为 0,部署后在 300+ 节点全球生效。运行时是标准的 Web API(
fetch/Request/Response),写起来像 Service Worker。 - Vercel Edge Functions / Middleware:同样基于 V8 isolate,和 Next.js 深度集成,跑在 Vercel 的 Edge Network 上。Next.js 的
middleware.ts默认就是 Edge Runtime。 - Deno Deploy:Deno 官方的边缘平台,也是 isolate 模型,API 兼容 Web 标准。
架构示意:
用户请求
|
v
[就近的边缘节点 POP]
|
├── Edge Function 执行(轻量逻辑)
| - 鉴权 / 重写 URL / A-B 分流
| - 读 KV / D1 / Edge Config(边缘存储)
|
├── 命中? --> 直接返回(无需回源)
|
└── 未命中 --> 回源中心 API / DB
关键区别在第一段:传统架构是"边缘只转发,逻辑全在中心";边缘架构是"边缘先处理,处理不了才回源"。对于鉴权、重定向这种 1ms 内能完成的逻辑,从 200ms RTT 降到 5ms,体验提升是数量级的。
四、什么适合放到边缘
不是所有逻辑都该上边缘。适合边缘的特征:轻、快、无状态、读多写少。
- 路由与重定向:地理位置分流(中国用户走 cn 域名)、
/old-path→/new-path、灰度发布按 Cookie 分流。Next.js Middleware 最典型的用法。 - A/B 测试:按用户 ID 哈希分流,在边缘就决定渲染哪个版本,中心完全无感。
- 鉴权与 bot 拦截:校验 JWT、检查 session Cookie、拦爬虫。验证失败直接 401,根本不回源,省的是中心算力和带宽。
- 简单 API 聚合:把几个后端接口的结果在边缘拼装一下返回,减少客户端往返。
- 轻量 SSR / 个性化页面:页面骨架在边缘渲染,中心只补数据。
- Edge Config / KV 读取:Feature flag、配置开关这种高频读、低频写的数据,放边缘 KV 最合适。
一个判断标准:这段逻辑如果搬到边缘,能不能在 50ms 内跑完并且不需要查中心数据库? 能,就放;不能,就老实放中心。
五、什么不适合放到边缘
这一节比上一节更重要,因为很多团队上边缘是跟风,最后踩坑才回来。边缘运行时有硬性限制,记住这些边界:
1. 重计算不行。Edge Runtime 是 isolate,不是完整 Node.js,CPU 时间有严格上限(Cloudflare 默认 10–50ms CPU,超出直接杀)。图片处理、视频转码、大列表排序、复杂推荐模型——统统放中心。
2. 大依赖不行。Vercel Edge Function 单个部署压缩后通常 1–4MB 上限,Cloudflare Workers 免费 1MB / 付费 10MB。你引一个 lodash 全量包、一个 ORM、一个 markdown 解析器加起来就爆了。Next.js 的 Edge Runtime 只暴露了 有限的 Web 标准 API 子集,fs、child_process、大部分 Node 原生模块都用不了。
3. 持久连接不行。Edge 是请求-响应模型,WebSocket、长轮询、SSE 长连接在边缘跑不稳。需要长连接就走专门的中心服务或 Durable Objects 这种特殊形态。
4. 强一致 DB 不行。边缘节点离中心数据库物理上还是很远,如果一个 Edge Function 每次都要读主库做强一致事务,那"就近"的优势就荡然无存——你只是把延迟从用户→中心,换成了边缘→中心。边缘读要用边缘存储(KV / D1 / Turso / Edge Config),最终一致即可;强一致写永远放中心。
5. 依赖 Node 生态的库不行。任何用到 Buffer.slow、node:crypto 的某些算法、sharp、mongoose 的代码,在 Edge Runtime 直接报错。迁移前一定跑一遍构建。
一句话总结:边缘是用来做"门卫"和"快递员"的,不是用来做"工厂"的。
六、CDN + Edge 的组合拳:动态也快、静态更省
真正的生产架构不是二选一,而是分层组合。一个成熟的 Next.js 应用通常长这样:
用户请求
|
[全球边缘节点]
/ \
静态资源(_next/static) 动态请求(页面/API)
| |
[CDN 缓存] [Edge Middleware]
命中直接返回 鉴权 / 分流 / 重写
(1 年 immutable) |
[Edge SSR 或回源]
/ \
ISR 命中? 回源中心
直接返回缓存的 访问中心 DB
静态化 HTML 做重业务逻辑
分层原则:
- 第一层 CDN:所有带 hash 的静态资源走 CDN 长缓存,永远不回源。
- 第二层 Edge Middleware:在边缘做鉴权、AB、地理分流,失败 / 简单请求就地终结。
- 第三层 Edge SSR / ISR:页面在边缘节点渲染或读 ISR 缓存,只渲染一次,后续命中。
- 第四层中心:只有真正需要查主库、跑重逻辑的请求才回源。
效果是:90% 的请求在边缘就处理完了,中心服务器只看到 10% 的"重活"。这才是边缘架构的 ROI 所在。
七、Next.js 的 Edge Runtime:能跑什么、该跑什么
Next.js 把边缘能力暴露成了几个 API,选型时要清楚取舍:
middleware.ts:永远在 Edge Runtime 跑。只放鉴权、重写、重定向、Header 操作这种纯逻辑,别放任何重活。它跑在每个请求的前面,慢一毫秒整个站点都慢。- Edge SSR:给页面加
export const runtime = 'edge',页面就在边缘节点渲染。优势是全球低延迟,劣势是不能跑 ISR(Edge 模式下 ISR 受限),依赖也只能用 Web 标准 API。 - Node.js Runtime(默认):完整 Node 能力,支持 ISR、所有 npm 包,但只在中心区域跑。
实战取舍:
- 首页、营销页、登录页这种全球访问、轻数据、强个性化的页面 → Edge SSR。
- 博客、文档、商品详情这种内容稳定、可静态化的页面 → Node Runtime + ISR,生成的 HTML 走 CDN。
- 后台管理、数据分析、复杂表单 → 老老实实 Node Runtime 中心跑。
不要为了"Edge"而 Edge。一个判断办法:先量延迟。如果你的用户 90% 在一个区域,中心部署就够,边缘是过度工程;如果你的用户横跨三大洲、首字节时间(TTFB)经常 300ms+,那边缘是必修课。
小结
把这套东西消化成几条实战准则:
- 物理延迟治不了,只能绕开。光速是硬限制,优化方向永远是"推近用户"——CDN 推内容,Edge 推计算。
- CDN 的核心是缓存策略,不是缓存本身。缓存键、TTL、失效(Cache Tag /
revalidateTag)三件套才是工程难点。带 hash 的资源给永久缓存,HTML / API 给短 TTL + 主动失效。 - Edge Function 适合做门卫,不适合做工厂。鉴权、分流、重写、轻 SSR、读 KV——放边缘;重计算、大依赖、长连接、强一致 DB——放中心。
- 边缘运行时有硬性限制,CPU 时间、包体积、API 子集都要提前验证。Next.js 的 Edge Runtime 不等于浏览器,更不等于 Node.js。
- 生产架构是分层组合,不是二选一。CDN 静态 → Edge Middleware 鉴权 → Edge SSR/ISR 渲染 → 中心 DB 重逻辑,把 90% 请求终结在边缘。
金句:边缘不是把后端搬到世界每个角落,而是把"门卫"和"快递员"派到每个街角——重活还是得回工厂干。
Related