“cloudflare-os”这个词,第一次看到的时候我也愣了一下——Cloudflare什么时候出操作系统了?实际上,它并不是一个官方产品,而是过去两年开发者圈子里很流行的一种玩法:把自己整个应用的技术栈“移植”到Cloudflare的生态里,让DNS、CDN、边缘计算、对象存储、数据库、身份验证全部由Cloudflare提供,自己的服务器只保留一个“可关机”的状态,甚至彻底归零。听起来很激进,但我花了大概三周时间,把手上一个跑了三年的网站完整搬了过去,最后VPS直接退了,省下的不只是账单数字,还有神经。
这篇东西就是给你梳理清楚:cloudflare-os到底是怎么拼起来的、每个组件用在哪、迁移和部署时有哪些坑,以及什么时候你不应该这么玩。适合谁看?独立开发者、个人站长、小团队里负责基础设施的人,还有对“免运维部署”感兴趣的技术爱好者。如果你手上正好有一个读多写少、以内容和API为主的项目,这套思路大概率能帮你省掉一大半的运维活。
1. cloudflare-os到底是什么:先别急着理解成“操作系统”
1.1 一个高估的名字,一个被低估的架构
Cloudflare官方从没发布过叫“cloudflare-os”的操作系统。这个说法是社区里对“Cloudflare Native Architecture”的一种意译——意思是说,你把传统跑在VPS或者云主机上的那套东西(Nginx、PHP、MySQL、Redis、对象存储),每一项都替换成Cloudflare旗下的对应服务。这么一来,你的应用其实就跑在Cloudflare分布在全球几百个城市的边缘节点上,“机房”这个抽象概念直接消失了。
我习惯用一个类比来跟朋友解释这件事:以前自己租服务器就像租了间毛坯房,水电、煤气、门窗、装修样样自己来,Nginx配置是水电工,MySQL调优是泥瓦匠,半夜宕机等于下水道堵了还得自己通。而cloudflare-os这套玩法,相当于搬进了一个精装服务式公寓——前台、保洁、安保、维修全都物业管了,你只负责把家具摆好(也就是写好业务代码)。也可以用家里的说法:传统VPS既要管“操作系统内核”,还要管“花园里的每一根草”;而Cloudflare原生应用就是你只管自己的草,别人的花园交给物业。
这套架构的组成大致是下面这张表:
| 传统组件 | cloudflare-os里的替代品 | 最核心的好处 |
|---|---|---|
| DNS解析 | Cloudflare DNS | 解析节点全球覆盖,自带防攻击 |
| Nginx / Web Server | Cloudflare Pages 或 Workers | 边缘托管,免运维,自动CDN |
| PHP / Node后端 | Cloudflare Workers (边缘函数) | 跑在靠近用户的节点,冷启动低 |
| MySQL / PostgreSQL | D1 (边缘SQLite) | 不占服务器进程,按量付费 |
| Redis / Session | Cloudflare KV | 天然分布,读写快,适合配置类数据 |
| 对象存储 / 图床 | R2 | 出口流量免费,和S3 API兼容 |
| 文件上传/下载 | R2 Presigned URL | 直传对象存储,绕开后端带宽 |
| 内网穿透 / 暴露本地服务 | Cloudflare Tunnel | 不开端口、不暴露IP,自动HTTPS |
| 后台登录认证 | Cloudflare Access | 邮箱OTP或SSO,前置身份验证 |
| WAF / 防CC | Cloudflare WAF / 速率规则 | 免费额度内的基础过滤已经够用 |
这张表就是cloudflare-os的“内核调度图”。理解了这个映射关系,后面所有的操作都只是在给这个架构填充业务而已。
1.2 为什么我决定把“服务器”关掉
我的原始项目是一台2C2G的小VPS,跑了Nginx + PHP + MySQL,上面挂着一个内容站点和一些小工具API。坦白说,大部分时间它都挺稳的,但只要遇到下面这些情况,我就得半夜爬起来:
- 某个页面被爬虫盯上,CPU瞬间跑满,SSH慢得敲命令都卡;
- 源站证书忘了续期,早上起来发现全站HTTPS挂了;
- CDN和源站缓存冲突,改了文章死活不更新,用户看到的还是旧内容;
- 每月固定一笔VPS账单,再加上对象存储的流量费,钱虽然不多,但总觉着花得不值。
搬上cloudflare-os之后,变化非常直观:Pages负责托管静态页面和前端资源,CDN直接缓存到边缘;动态接口全部做成Workers函数,按请求计费;数据层用D1存结构化内容,R2存图片和附件;后台管理路径用Access锁起来,我自己通过邮箱验证码登录,彻底告别“改了 .htaccess 或者 Nginx location”这种操作。VPS退了以后,我一个月下来的账单基本是零或者几分钱,而且全站的响应速度反而比之前更快了,因为资源离用户更近。
当然,这个方案不是万能的。后面我会专门说清楚边界——它更适合个人项目、内容型站点、轻量API;如果要做强一致性的事务型业务、超长WebSocket连接、或者需要深度定制网络协议的东西,Cloudflare原生方案就不该硬上。选型之前先判断好场景,这才是最关键的。
2. 组件拆解:把Cloudflare拼成一个可用的系统
2.1 边缘计算:Workers 和 Pages,两兄弟各有分工
先分清这两个东西:Cloudflare Pages 偏重“托管静态站点 + 轻量服务端函数”,Cloudflare Workers 则是纯粹的边缘函数运行时。Pages适合博客、文档站、前端应用这类以静态资源为主的场景,你只需要构建出 dist 目录,上传或连上Git仓库,Pages会自动分发到全球边缘节点;它的Pages Functions也支持在同一个项目里跑接口逻辑,适合小流量场景。
Workers更“程序员向”:它运行在一个叫V8 isolate的轻量级运行时里,每个Worker实例都很便宜,冷启动时间极低,几乎感受不到“函数计算”那种等待。比如最简单的接口处理:
export default { async fetch(request, env, ctx) { const url = new URL(request.url); if (url.pathname === "/api/hello") { return new Response( JSON.stringify({ ok: true, msg: "hello from cloudflare edge" }), { headers: { "content-type": "application/json" } } ); } // 如果项目同时绑定了静态资源,就交给静态产物处理 return env.ASSETS.fetch(request); } }这段代码最关键的点在于最后一行:env.ASSETS.fetch(request)。Workers和Pages绑定之后,你可以把静态资源和动态逻辑放进同一个项目,请求来了先匹配动态路由,匹配不到就走静态资源。这样就不需要单独买个VPS来“同时处理HTML和API”。
在实际架构里,我推荐的配合方式是:前端/内容主体放Pages,评论接口、表单提交、阅读计数、订阅推送这类“轻逻辑”放Workers或Pages Functions。两者共用同一个域名,用户感知上就是同一个站点,但底层已经被边缘网络拆成多级缓存和函数资源了。还有个加分项:Pages自带版本历史和一键回滚,改出问题可以直接退到上一版,这在以前VPS部署上是需要手动备份的活。
2.2 数据与存储:D1、R2、KV,别用错
这是cloudflare-os里最容易踩坑的部分,因为三个存储服务的名字相似,但各自定位完全不同。
D1是基于SQLite的“边缘数据库”,托管型,兼容SQL语法,适合存业务结构化数据,比如文章、评论、用户资料、订单记录。D1可以理解成“SQLite跑到云上,并且被Cloudflare管理好了”——单库容量虽然不像传统MySQL那么“无限”,但个人项目的体量完全用不满,免费额度内就很能打。
KV是一个全球分布的键值存储,最大特点就是“最终一致性”,写入了一条数据,要过一会才能在全世界所有边缘节点读到一致的值。它适合存配置、缓存、读多写少的会话片段,不适合存账号余额这种不能等延迟的数据。记住一个判断口诀:能接受“稍后看到最新值”的数据放KV,不能接受的放D1。
R2则是对象存储,对标S3,但有一个极其重要的区别:R2出口流量不收费。传统S3如果你流量大了,带宽账单就是个吞金兽;而R2这个设计对个人图床、视频、备份文件简直是雪中送炭。
三个服务的选择可以参考这张速查表:
| 存储服务 | 适合内容 | 一致性 | 典型用量 | 备注 |
|---|---|---|---|---|
| D1 | 文章、评论、订单、关系型数据 | 强一致(主库),在读副本上有延迟 | 个人站长通常规模很小 | SQLite语法 |
| R2 | 图片、视频、压缩包、静态资源 | 强一致(对象级) | 免费10GB左右起步 | S3 API兼容,无出口流量费 |
| KV | 配置、Session、缓存 | 最终一致 | 读多写少 | 极低延迟,适合热路径 |
拿我自己举例:文章正文和评论都存在D1,因为数据之间有关联,查询需要SQL;网站配图和用户头像存在R2,因为它们是典型的大对象资源;每个页面的预览配置、A/B测试标记这类小数据我放KV,因为需要全球快速读取,但对写后立即读到最新值的需求不高。
这里有个实操细节:用Wrangler创建和操作这些服务非常方便,后面第3节我会给出具体命令。你别光看存储选型,绑定方式也很重要——在wrangler.toml里声明好后,代码里直接用env.DB、env.BUCKET就能访问,密钥和连接信息Cloudflare已经在运行时注入好了,不用自己写配置文件或者环境变量,这点比老式VPS需要维护.env要轻松得多。
2.3 网络与接入:CDN、DNS和Tunnel,让流量自然流动
在cloudflare-os里,网络层不再是你需要“配置”的东西,而是默认具备的能力。你把域名托管到Cloudflare之后,DNS解析和CDN加速是天然集成的。看似简单,背后有个逻辑:传统VPS方案里,DNS、CDN、源站是三个独立系统,你需要在CDN后台填源站IP、在DNS后台做A记录、在源站Nginx里配缓存规则;而Cloudflare整套方案里,流量先打到边缘网络,该缓存的缓存、该回源的才回源,这本身就是“OS的内核行为”。
Tunnel是这套组合里我最喜欢的一个组件。它的作用是把“本地的服务”通过cloudflared这条隧道安全地暴露到公网,不需要公网IP、不需要在路由器上做端口映射、更不需要在防火墙上开洞。最典型的用法就是你家里或办公室有一台开发机/NAS/内部小工具,你希望在外面也能安全访问,但又不想承担暴露公网IP的风险。一条命令的事:
cloudflared tunnel login cloudflared tunnel create mysite cloudflared tunnel route dns mysite example.com cloudflared tunnel run mysite这几条命令做的事情是:登录取证书,创建一个隧道,把这个隧道绑定到example.com的一个子域名,然后启动隧道。启动之后,本地的某个端口(比如http://localhost:3000)就会被Cloudflare边缘节点接管,用户在浏览器里访问example.com时,流量会通过隧道安全地转发到你的本地服务。整个过程自动签发HTTPS证书,源站的IP 100%不会暴露。对个人开发者来说,这意味着你可以把一台老旧笔记本当作“私人服务器”,从任何地方访问;对于小团队,这意味着内网工具不需要专门买公网服务器了。
强调一下,Tunnel的最佳用途是开发预览、内部系统、轻量运维入口。如果你的业务是面向大众的高并发生产服务,我并不建议把Tunnel当作唯一入口,因为它的链路里多了一层到本地的回源,本地上行的稳定性会直接影响用户体验。这个边界要心里有数。
2.4 安全与身份:Access、WAF,这是自带门禁的“登录功能”
cloudflare-os里,安全不只是“加个HTTPS证书”这么简单。Cloudflare Access是我迁移之后瞬间幸福感爆棚的功能——它本质上是一个“身份验证代理”,放在你的域名前面。用户访问你保护的路径时,必须通过邮箱OTP验证码、Google登录或其他身份提供商认证,验证通过后才会被放行。这意味着你不需要在自己的代码里写登录页面、管密码哈希、操心Session过期逻辑,Access全部接管。
拿我自己的后台举例:我用Access保护了/admin/*路径,自己登录时输入邮箱,Cloudflare会发一个一次性验证码,验证通过后浏览器得到会话Cookie。整条流程我不需要在自己应用里存任何用户表,也不需要配SSL客户端证书,安全性比我以前在Nginx里写Basic Auth高了好几个数量级。
WAF则提供了一层面向公网的过滤:你可以配置速率限制规则、防火墙规则,拦截恶意IP和异常爬虫。Cloudflare的免费层级里已经有不少基础规则,个人站日常足够用。我会建议所有人把“管理后台”默认保护起来,哪怕站点本身没什么敏感内容,至少能防止别人往里灌垃圾数据。
到这里,其实“操作系统”的拼图已经完整了:Workers/Pages提供计算,D1/R2/KV提供存储,CDN+DNS+Tunnel提供网络,Access/WAF提供安全。接下来我就用一条实际的项目迁移过程,把这些东西全部串起来。
3. 实操:从零搭建一个“cloudflare-os”应用
3.1 准备阶段:域名、账号、CLI
要开始之前,你需要三样东西:一个Cloudflare账号、一个域名、本地的Wrangler CLI工具。域名这一步很关键——我推荐直接把域名的Nameserver迁移到Cloudflare,而不是只用CNAME接入。原因有两个:第一,DNS解析节点足够分散,解析速度快;第二,只有完整接入之后,Cloudflare的CDN、WAF、Access这些能力才能真正“控制”到你所有子域名的流量。
本地安装CLI很简单,Node.js环境下:
npm install -g wrangler wrangler loginwrangler login会在浏览器里弹出授权页面,确认之后,你的终端就拥有当前账号所有资源的操作权限了。之后所有创建、部署、查询工作都可以在命令行里直接完成。
有一点要提醒:如果你是在公司网络或者共享电脑上操作,用完后记得wrangler logout,避免令牌残留。虽然Cloudflare的令牌有作用域限制,但习惯上还是谨慎点好。
3.2 静态站点部署到 Pages
Pages的部署方式有两种。一种是通过Git接入,每次push自动构建发布;另一种是用Wrangler手动上传构建产物。对于个人项目,我建议先从手动上传开始,简单直接,看得见摸得着:
npx wrangler pages deploy ./dist --project-name=myblog这里的dist是你的前端构建输出目录,比如Vite项目默认就是dist,Hugo、Zola这类静态生成器也都有自己的输出目录。Pages上传成功后,会返回一个默认的*.pages.dev域名,你可以直接访问,后续再绑定自己的域名。
Pages比较贴心的一点是:每个部署都带独立的Preview URL,你可以在正式上线前先自己看看效果;如果线上版本出了问题,Dashboard里一键就能回滚到历史版本。这个功能以前我在VPS上完全靠“本地保存一份旧代码”来兜底,太原始的。
3.3 用Workers写动态接口
有了静态页面之后,你会很快遇到动态需求:评论、表单提交、订阅、统计、搜索代理。传统思路是在VPS起一个后端;cloudflare-os的思路是直接写一个Worker。
以Hono为例,Hono是一个专门针对边缘运行时的Web框架,特别轻量,写出来的代码也清晰:
import { Hono } from 'hono'; const app = new Hono(); app.get('/api/views/:slug', async (c) => { const slug = c.req.param('slug'); // 这里是读取KV或D1的计数逻辑 return c.json({ slug, views: 1024 }); }); app.post('/api/comment', async (c) => { const body = await c.req.json(); // 校验后写入D1 return c.json({ ok: true }); }); export default app;写完代码后,在wrangler.toml或者wrangler.jsonc里配置环境绑定,然后部署:
wrangler deploy部署完成之后,Worker就会运行在离用户最近的Cloudflare边缘节点上。没有容器启动过程,没有端口监听配置,没有进程守护,请求来了就执行,执行完就释放。这种感觉就像写了一个“全局函数”,系统自己会帮你决定该在哪里跑、怎么并发、怎么扩容。
关于绑定,多说一句。绑定就是把D1、R2、KV这些资源和Worker关联起来,运行时通过env注入给你。绑定之后你可以在代码里直接用env.DB、env.BUCKET,再也不用关心连接串和密钥。这也是我为什么说cloudflare-os的核心体验是“少干活”——连接基础设施这件事,系统托管了。
3.4 接入R2和D1:把数据层搬到边缘
先创建存储资源。一条命令一个桶:
wrangler r2 bucket create assets然后在wrangler.toml里加上对应声明:
[[r2_buckets]] binding = "BUCKET" bucket_name = "assets"写一段上传逻辑,前端直传文件到你自己的API,Worker生成一个临时签名URL,再由前端用这个URL直接访问R2对象:
async function handleUpload(request, env) { // 从请求中读取文件名和类型 const key = `uploads/${Date.now()}_${filename}`; await env.BUCKET.put(key, await request.arrayBuffer(), { httpMetadata: { contentType: fileType } }); return new Response(JSON.stringify({ key })); }R2还有个很爽的特性:支持生成预签名URL,让客户端直接读写对象。比如你想让用户上传头像,后端给他一个带签名的URL,他就能直连R2上传,文件完全不经过你的Worker,带宽压力瞬间为零:
const url = await env.BUCKET.createPresignedUrl(c.executionCtx, key, 60); return c.json({ uploadUrl: url });D1的操作逻辑类似。先用Wrangler创建数据库:
wrangler d1 create mydb然后写一个表结构和插入语句:
CREATE TABLE IF NOT EXISTS comments ( id INTEGER PRIMARY KEY AUTOINCREMENT, post_id TEXT NOT NULL, author TEXT NOT NULL, content TEXT NOT NULL, created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP );wrangler d1 execute mydb --file=./schema.sql最后在Worker里查询:
app.get('/api/comments/:postId', async (c) => { const { postId } = c.req.param(); const res = await c.env.DB.prepare( "SELECT * FROM comments WHERE post_id = ? ORDER BY created_at DESC" ).bind(postId).all(); return c.json(res.results); });这里有个很关键的体验:D1的API使用了prepare().bind().all()这种形态,和很多Node生态的SQLite库非常像,迁移成本低。而且,D1直接支持从SQLite的本地数据库文件导入。如果你以前项目里用的是MySQL,导出成SQL,再导入到D1,语法上基本不用改太多。
3.5 用Access保护后台路径
数据层搞定了,别忘了安全层。进入Cloudflare Zero Trust的Dashboard,添加一个应用,填上你要保护的域名和路径模式(比如example.com/admin),然后选择访问策略。
我这里建议直接把“允许访问”的控制粒度做到邮箱级别——你可以指定只有你自己的邮箱能登录,其他任何人来都要被拦在门外。验证方式选择“一次性验证码(OTP)”最省事:用户输入邮箱,Cloudflare发验证码,输入正确就放行。整个过程我没有写一行业务代码,这就是前面说的“门禁系统”的价值。
这套做法远比传统“给后台加个密码”安全,因为身份验证发生在Cloudflare边缘,连你的源站接口都不会被恶意请求打到。
3.6 Tunnel接入本地设备(可选)
最后,如果你想把自己的本地设备也纳入cloudflare-os的管辖,Tunnel是压轴戏。我自己的一个实际案例:家里放了一台旧ThinkPad跑着一个内部数据统计服务,IP是动态的,以前要从外面访问得配合动态DNS再加路由器端口映射,折磨了不知道多少个晚上。后来我直接在ThinkPad上装了cloudflared,和前面那条命令一样,本地服务瞬间有了自己的公网域名,证书自动签发,我人在地铁上也能打开家里的统计看板。
实际上Tunnel有两种用法:一种是像上面命令那样,单机安装cloudflared直接运行;另一种是在Cloudflare Zero Trust面板里创建Tunnel,然后生成一个token,把token放进本地配置文件。两者的效果一样,后者方便集中管理,前者适合快速实验。
要提醒的是,本地设备接入后,这条链路的稳定性取决于你家里的上行宽带。轻度访问没问题,但别指望它能扛住大量并发流量。
4. 常见问题与排查技巧实录
再完美的架构,实操中总会遇到各种奇奇怪怪的问题。我把迁移过程中踩过的坑、查过的文档、以及跟朋友讨论出来的经验,整理成一个速查表式的清单。如果你也正在往cloudflare-os上搬项目,大概率能帮你省下好几个晚上。
4.1 页面更新了却一直显示旧内容
这是从传统VPS迁到Cloudflare之后最普遍的问题,本质原因就是CDN缓存没有失效。传统VPS上你改了文件立刻生效,但边远节点可能还会继续提供旧的缓存版本。解决思路有两个层面:如果是开发调试阶段,可以把页面返回头的Cache-Control设置成no-cache或者直接在Dashboard的Cache Rules里加一条“绕过缓存”的规则;如果是正式发布想强刷,可以到Dashboard用Purge Cache清理全网缓存,精准点的做法是只清理单个URL。
实际操作里我的偏好是“开发环境不缓存+生产环境版本化文件名”。前端构建工具会在资源文件名里带上哈希,改动后文件名变化,天然绕过缓存;HTML页面设置短缓存或no-cache,内容更新立即生效,静态资源照样被边缘缓存加速,两边都不耽误。
4.2 R2跨域导致图片加载失败
如果你在浏览器里用JavaScript直接fetch R2里的对象(比如通过预签名URL),经常碰到“CORS policy”错误。原因很简单:R2默认只允许同源请求,跨域请求需要显式配置允许的来源域名。
解决步骤:进入R2 Bucket的Settings,找到CORS,添加一条规则,允许的来源填你的站点域名,Allowed方法选择GET、PUT,Allowed Headers填*。配置完成后,浏览器就能正常跨域读写R2了。这个坑几乎每个从传统图床迁移过来的人都会踩一次,因为以前对象存储服务和Web应用是同一域名的后端代理,不存在跨域问题。
4.3 D1查询慢或者偶发超时
D1的查询延迟一般都在几十毫秒内,但如果你的表缺索引,或者应用写得太随意,边缘数据节点也会有压力。最典型的错误是没有建索引:
CREATE INDEX idx_comments_post_id ON comments(post_id);另外一个经验是:别在循环里一条一条执行D1的insert,要用batch接口把多条写操作合并提交。D1的批处理比逐条执行快得多,而且更省钱。调试的时候也可以分清楚--local和--remote:前者本地模拟调试,后者直接操作线上数据,写错了一定要小心。
4.4 Workers免费额度报警
Workers免费计划每天有请求次数限制,正常情况下个人项目根本打不满,但如果你的接口被爬虫或者某些自动化脚本疯狂刷新,很容易触发限制。处理思路:先到Dashboard看流量报表,找出哪些请求路径在滥用;然后把高频访问的响应加缓存,把重复计算移到KV里做“原子缓存”。我见过有人把整个API响应按参数缓存15分钟,流量成本瞬间降了一个数量级,用户体验还更好了。
4.5 SSL/TLS模式选择不对
如果你接入了Tunnel,Cloudflare的SSL/TLS模式要设成Full (strict),因为Tunnel和Cloudflare边缘之间已经是加密链路。如果你用的是传统源站,根据自己的证书情况选择Full或Flexible,但千万别在Flexible模式下要求源站必须HTTPS,否则会出现循环重定向。这个问题的表现是“网站打不开,浏览器提示重定向次数过多”,排查起来也很简单:Dashboard里看清楚TLS模式,再把源站侧的强制跳转会去掉。
4.6 Access登录循环或者验证码收不到
Access登录循环八成是Cookie域或路径问题。确保Access应用配置的路径和你访问的路径一致,比如你保护的是admin/*,但访问的是/admin(没有斜杠),规则可能匹配不上。收不到验证码的情况,先检查邮箱垃圾箱,然后看看Zero Trust面板里邮件发送日志——如果是免费邮箱频繁收验证码,可能会有频率限制,过几分钟再试就好。
5. 什么时候不该用cloudflare-os
讲了这么多好处,我不能只报喜不报忧。cloudflare-os这套架构虽然有它的优雅之处,但也有非常清晰的边界,硬跨边界用,是要吃苦头的。
第一个不适合的场景是“强一致、高事务”的业务系统。D1虽然够快,但毕竟是SQLite为底层的托管服务,大量并发写、复杂事务、跨表强一致的诉求,它并不比传统MySQL/PostgreSQL更合适。如果你在运营一个账号体系复杂、多租户、订单对账要求极高的SaaS,请冷静,不要因为“免运维”三个字把自己的核心交易数据交给一个你没完全掌控的平台。
第二个不适合的场景是“低延迟实时交互”。Workers虽然冷启动快,但它运行在Cloudflare的V8 isolate里,不像长期驻留的WebSocket服务那样适合海量长连接。你要做一个实时协作文档、在线游戏房间,还是老老实实考虑专门的边缘实时服务,不要拿Cloudflare全家桶硬扛。
第三个考虑维度是“平台锁定”。所谓cloudflare-os,本质上是在接受Cloudflare生态作为一个“底座”。好处是你少写几千行运维代码,代价是你深度依赖了它的产品形态。好在Cloudflare在设计上其实留了很多后门:Workers代码本质是JavaScript,迁出成本低;R2兼容S3 API,完全可以被其他对象存储替代;D1是SQLite格式,数据可以导出成标准SQL文件。
所以我的真实建议是:对于个人项目、内容站、小工具、轻量API,cloudflare-os几乎是“最优解”级别的选择,成本低、上手快、免费额度高;对于严肃的商业生产系统,你可以把这套方案当作“前置层”——静态资源、缓存、边缘逻辑放Cloudflare,核心业务数据仍旧留在自己可控的数据库里。混合架构从来不是丢人的事,反而是一种更成熟的架构人生观。
我在实际操作中体会最深的一点是:把云服务当成操作系统,最大的风险不是技术,而是“你忘记了自己活在一个托管生态里”。所以我在整套迁移完成后,额外做了一件事:每周定时把D1的数据导出成JSON,R2里的关键文件在本地硬盘保留一个副本,Workers的代码也提交到Git仓库。这些东西平时用不上,但一旦哪天Cloudflare的策略变了、价格调了、或者我的业务需求超出它的边界了,我能带着全部数据体面地离开。
最后再分享一个小技巧:给自己的关键资源加个“外部哨兵”。我写了一个定时触发的Worker,每天检查一遍核心API和页面的HTTP状态码,有问题就通过邮件通知自己。这比任何监控面板都实在——cloudflare-os接管了基础设施,但“业务有没有挂”这件事,永远得有人盯着。