案例 Cloudflare Blog 迁移到 EmDash:从压测到灰度上线的工程师复盘

2026-08-27 21:24:53 views 5

Cloudflare Blog 迁移到 EmDash:从压测到灰度上线的工程师复盘

一个还没到 1.0 的 CMS,敢不敢直接接管一个常规 75 RPS、峰值能到 5000 RPS 的博客?Cloudflare 的答案是:先拿自家博客试。8 月 12 日,Cloudflare Blog 全量迁到自研系统 EmDash。这篇文章不是产品发布稿,而是记录我们怎么判断“能不能用”、怎么把它压到极限、以及切换过程中踩到的坑。

Customer Zero:把自己变成第一个苛刻客户

在 Cloudflare,Customer Zero 不是市场话术。产品上线前,先用自己的业务跑,跑出问题就修,修到真实规模、真实安全压力和真实编辑流程都过关,再交给客户。这种倾向也写进了内部工程标准 Codex:如果要引入外部供应商,必须先说明内部方案为什么满足不了,缺口是真实需求还是一次性偏好。

EmDash 发布时,加上当时 CMS 供应商的一些限制,我们清楚博客团队大概率会成为 EmDash 的第一个生产客户。于是,这个高流量、流量形态极端的网站,成了所有内部验证的第一块试验田。

迁移前只问两个问题

评估被压成两个朴素的问题:EmDash 适不适合我们?能不能扩展?

能不能用起来:编辑流程走一遍

“能不能用”听起来简单,但对一个还没到 1.0 的平台,答案必须来自真实编辑流程。我们逐项验证了发布后下线、撰写新文章、定时发布、添加媒体资源等日常操作。

整体能撑住,但 Cloudflare Blog 的复杂度也撞出了几类问题:体量上,媒体、内容实体搜索和作者署名比普通站点重得多;细节上,本地化、SEO、CSP 这些不能出错;效率上,自定义 HTML 块不好找、实体内编辑器有 bug、写长文时格式工具栏会离开视野。

最大的缺口是定时发布,直到 0.19.0 才真正解决。对早期项目可以理解,但对博客团队来说,这类问题必须在预定发布时间之前被发现,而不是之后。

能不能扛住:k6 三档压测

第二个问题更硬。Cloudflare Blog 的流量形态很不均匀,峰值既有热门文章带来的,也有像被刻意打一点流量观察反应的。对 Cloudflare 来说,性能也是产品承诺,于是我们用 k6 设计了三类场景:

  • Ramp:逐步提高请求到生产基线三倍,再降温。
  • Breakpoint:10 分钟内从 0 增加到 100 RPS,直到系统出现问题。
  • Burst:直接施加 7000 RPS 瞬时负载,观察系统反应。

每个场景有三个判定阈值,任一不达标即失败:

  • 可用性:超过 0.01% 请求返回 5xx
  • P95:超过 5% 响应大于 500ms
  • P99:超过 1% 响应大于 1000ms

压测结果、内部讨论和数据汇总后,生产架构逐渐清晰:EmDash 运行在 Worker 上,前置新的 Workers Cache,再加一层基于 Workers KV 的对象缓存(EmDash 团队为这个场景专门构建,我们相信这是最早这样做的重大站点之一),最后通过 Hyperdrive 连接 PlanetScale。

多层缓存的效果很直接:99.5% 的静态文件、约 70% 的请求在缓存层结束,数据库压力小了很多。

前端重设计:换皮肤也解决了一个老问题

后端迁移解决承载力,前端重设计解决归属感。基于 Kumo 设计系统重建界面后,博客与首页、控制台、营销站点共享同一套视觉语言,不再像孤立角落。

浅色/深色模式原生支持,跟随系统偏好,也保留显式开关,两种状态都按无障碍标准校验。一个有趣的老问题也被解决:订阅框原来在右上角,常被误认成搜索框,用户把搜索词直接输进去。现在订阅入口移到文章底部,读者读完想关注时,提示正好出现。

架构定了,剩下的问题是:怎么让读者完全无感地完成切换?答案不是一次猛切,而是代理加灰度加回退。

我们部署了一个代理 Worker,在旧博客和新 EmDash 站点之间分流。Worker 通过版本 Cookie 决定请求进入哪一侧;一旦新站出现 500,流量可以退回旧博客。另一个关键细节是 NEW_BLOG Service Binding 带来的 Worker 直连:代理不再绕经公共主机名、DNS、TLS 和出站 HTTP,请求直接从代理 Worker 派给新博客 Worker,延迟更低。

上线当天,流量从 1% 开始,验证健康后逐步走到 5%、15% 和更高比例。每一步都暴露真实生产环境的边角问题,但不会影响大多数读者。当天结束前,100% 流量进入新平台。

结果:P95 曲线变平了

对比旧架构与新 EmDash 架构的 P95 响应延迟,两种形态完全不同:旧平台在负载下周期性冒出延迟尖峰,新系统基本保持平坦。这些收益发生在最高约 850 RPS 的真实流量下,错误极少。

MCP:博客不只是给人读的

这次升级还有一条容易被忽略的主线:博客正在变成 Agent 也能直接使用的资源。

第一层是读取。我们发布了新的 Model Context Protocol(MCP)服务器,Agent 可以调用 search_postslist_postsget_postlist_tags。因为 Worker 已经暴露了新的 EmDash API 与 AI 搜索端点,这个 MCP 只用几个小时就完成了。

第二层是生产。EmDash 自己也有 MCP 服务器,作者可以用它浏览、创建、编辑内容,处理发布和定时发布,删除文件,以及执行更多管理操作。Agent 工具正在成为 CMS 的标配,但不额外收费仍然少见;在这里,MCP 只是平台能力的一部分。

第一次大考:Agents Week

刚迁移完就遇上高密度发布。Agents Week 9 天发了 28 篇文章,接近 300 万次页面浏览,内容和访问同时加压。前端博客 Worker 在最高约 450 RPS 下稳定;期间 Cloudflare 内建 DDoS 防护吸收了一次 28000 RPS 的攻击。

编辑侧还是暴露出一些小问题,多数是交互体验的怪癖,也包括定时发布相关 bug,已反馈给 EmDash 团队,预计 Birthday Week 前修复。

工程师判断:这套方案的适用边界

作为参与验证的工程师,我想单独说说哪些经验可以带走,哪些不能盲目照搬。

适用的情况:你有自有运行时和基础设施,能把缓存、网络、数据库都控制在一个技术栈里。EmDash 的多层缓存、Service Binding 直连都依赖 Cloudflare 的运行时能力,换一个平台可能没有对应的原生产品。如果你有类似条件,并且业务对 P95 曲线稳定度有硬性要求(比如流量波动大),这套“压测+灰度+缓存分层”的打法是值得复用的。

不适用的情况:大多数站点不需要 KV 对象缓存,也不需要 7000 RPS 的 burst 压测。如果你的峰值只有几百 QPS,用常规 CDN 和关系型数据库就足够,过度设计反而增加维护成本。另外,编辑体验上的那些 bug——比如长文时格式工具栏跑出视野、定时发布到 0.19.0 才修好——恰恰说明早期平台自用验证的价值:只有真实编辑流程会把这种场景跑出来。这比任何演示环境都有效,但前提是你能容忍自己平台的“毛边”。

不是每个团队都有资源或意愿当一个平台的 Customer Zero。这更像是一种战略选择,而不是最佳实践。

一个值得留的问题

对正在选型 CMS 的团队来说,Customer Zero 这套做法到底值不值得学?在什么规模下,把自己变成第一个生产客户才划算?如果产品只有少量内部用户,投入大量工程资源去填早期平台的坑,可能还不如买成熟方案。但反过来,如果你有信心这个平台能长期拉低整体成本,早期自用验证可能就是最便宜的路径。

这个平衡点在哪里,我们也在找答案。

复制全文 生成海报 架构 运维 压测 CMS Cloudflare

推荐文章

程序员茄子在线接单