1.2 选型对比:自建后端与云开发的账
场景:迁移前的一次财务对拍
决定迁移之前,老板让我把账算清楚:继续用云开发,还是租 CVM 自建,差价到底多少。我没敢拍脑袋,把三个月的实际调用数据导出来做了张表。当时日活八千左右,云开发侧的云函数调用量每天二十二万次,其中近一半是信息流的分页拉取;云数据库读写每天六十万次;云存储流量每个月约一百二十 GB。按当时的计费方式,每月账单在四百元上下浮动,看上去不贵,但问题不在钱,在于能力边界。
真正的导火索是热榜聚合。产品要每十分钟把各版块的帖子按互动增速重排一次,云开发的定时触发器最短只能一分钟一次,跑得密了浪费调用次数,跑得稀了满足不了业务。而且聚合过程要频繁读写缓存,云开发里没有现成的 Redis 语义,只能拿数据库硬扛。几轮讨论下来,团队达成共识:不是云开发不好,是我们的业务形状不适合它。
论战并没有就此平息。反对派的理由也很充分:自建意味着招生死线全部自己背。有一段时间群里贴过一张对比图,左边是云开发出故障时的状态,右边是我们自己排障时的状态,前者是等官方恢复,后者是凌晨三点爬起来。老板最后拍板的逻辑很务实:看团队基因,我们有一个愿意扛后端的人,那就赌自建的红利;如果团队全是前端,这账就不是这么算了。
为了让这张表更可信,我还做了一次压力外推:把未来六个月的日活按两倍、五倍、十倍三档代入两条路线,分别算出月成本。云开发那一侧的函数调用次数和数据库读写次数基本随日活线性放大,到十万日活时每月账单奔着三千五去了;自建这一侧在十万日活时只要把 CVM 从两核四G升到四核八G、Redis 升到两吉,月成本合计两千出头,差距拉开近一倍。外推表不一定准,但它让选型讨论从信仰之争变成了算术题,会议室里反对的声音小了很多,毕竟没人愿意跟算术结论作对。
方案:两条路线逐项打分
我们做了两张并行成本表,一张是眼下月成本,一张是能力扩展性,权重各占一半。云开发的优点是省心,不用管机器、证书、备份;缺点是每个定制需求都要绕一圈。自建的优点是 Redis、定时任务、长连接全都自己说了算;缺点是什么都要自己管,包括最烦人的证书续期和日志收集。最终我们选了自建,但把存储留在 COS,没自己搭文件服务,这是折中后的决定:
| 对比项 | 云开发 | CVM 自建 | 我们的选择 |
|---|---|---|---|
| 月成本(八千日活) | 约 400 元 | 约 380 元 | 自建 |
| 定时任务粒度 | 最短一分钟 | 秒级可配 | 自建 |
| Redis 缓存 | 无原生支持 | 自由部署 | 自建 |
| 运维负担 | 近乎零 | 全包 | 云开发占优 |
| 流量峰值弹性 | 自动扩缩 | 需预算 | 云开发占优 |
| 图片存储 | 云存储 | COS 直传 | 二者皆可 |
外推表也一起放上,这是说服老板的关键。云开发费用随调用量线性放大,自建费用阶梯式跳档,日活越高差距越大:
| 日活规模 | 云开发预估 | 自建预估 | 差距 |
|---|---|---|---|
| 八千(当时) | 约 400 元 | 约 380 元 | 基本持平 |
| 两万 | 约 900 元 | 约 700 元 | 自建略省 |
| 十万 | 约 3500 元 | 约 2100 元 | 自建省四成 |
重点说一下成本那一行。自建的三百八十元里,CVM 两核四G一百三十元、MySQL 基础版九十元、Redis 一千兆规格四十元、COS 存储加流量约八十元、CLS 日志四十元。注意云开发省的不只是钱,还有一个人力:自建后我每周大概花四个小时在运维上,折算成工资远超那点差价。所以自建的前提是团队里得有一个愿意折腾后端的人,否则账面上赚的会以别的方式赔回去。折中方案也不是没有:核心接口自建、简单活动页留在云开发,两边的弹性都吃到了。
再补一个容易被忽略的隐性成本:故障恢复时间。云开发出问题,能做的是等官方公告;自建出问题,从定位到修复的时间完全取决于自己的监控和预案是否到位。我们专门统计过迁移前后的平均恢复时长,云开发时期两次较大故障都是等恢复,自建后两次同类故障我们自己二十分钟内修好。说白了,自建买的不只是机器,还是对系统命运的控制权,前提是你接得住。
配置与代码
自建方案的第一版清单很克制,只买够用的,后面随流量加。CVM 我们选了广州地域的两核四G,系统盘五十 GB,装 Node 运行时和 Nginx;MySQL 买同一地域的基础版,避免跨地域访问延迟;Redis 买最便宜的千兆主从版,只做缓存不做持久化依赖:
CVM 2核4G 广州三区 130元/月
MySQL 1核2G 基础版 90元/月
Redis 1G 主从版 40元/月
COS 存储120GB + CDN流量 80元/月
CLS 1亿条/月 7天保存 40元/月
迁移策略是新旧并行而非一把梭。先在 CVM 上把读接口跑通,小程序里按版块灰度切换,先切冷门版块观察一周,再切热门版块;写接口最后切,因为涉及审核流程。灰度开关放在小程序的启动配置里,出问题可以十分钟内切回云开发。这套流程我们写成了一份检查清单,从切流前到切流后共十四项,每一项都要值班同学逐条打勾,避免个别人凭记忆操作漏掉环境变量。下面这段是灰度配置的最小形态,开关只控制读路径,写路径不灰度直接推全量:
// 启动时拉取灰度配置
const cfg = await request('/api/boot/config');
if (cfg.feed_endpoint === 'self') {
baseURL = 'https://api.xiangyi.example';
} else {
baseURL = SERVICE_CLOUD; // 云开发域名兜底
}
灰度期间的数据对账也写成了脚本,每天早上跑一次,把新旧两端的帖子数、评论数、最新一条时间戳分别输出,任何一格差值超过十条就报警。这套对账脚本在第二周真的报过一次警:旧端有一条评论因网络重试重复写入,新端只有一条,对账帮我们在切换前就发现了双写重复的问题。
// 每日对账:新旧两端核心表计数对比
async function reconcile() {
const old = await oldDb.count('t_comment');
const newC = await newDb.count('t_comment');
if (Math.abs(old - newC) > 10) {
await alarm('评论数漂移: 旧库 ' + old + ' 新库 ' + newC);
}
}
踩坑
第一个坑是低估了运维时间。我以为装个 Node 跑个 PM2 就完事,实际上第一周光处理证书、日志切割、MySQL 备份脚本就熬了三个晚上,后来把日志全丢进 CLS、证书改成自动续期才算消停。第二个坑是灰度切换时双写不一致。有一周新旧库同时写评论,结果两边自增 ID 不同步,合并时楼中楼对不上,最后以新库为准手工修了三百多条数据。第三个坑是 COS 的流量费,第一次配 CDN 回源没注意,缓存命中率只有百分之三十,外网流量哗哗扣钱,调成七天过期、忽略参数缓存后,命中率提到百分之八十五,月费降了三分之一。第四个坑是 Redis 一开始买的是单机版,某次重启丢了半小时的热榜缓存,首页空白了十几秒,后来换主从版,并在启动时做缓存预热。第五个坑是迁移期间监控盲区,新旧双端同时跑的那两周,监控只盯着新端,旧端报错没人看,等客服反馈才发现老用户过着质量下降的日子,之后监控改为双端同屏。第六个坑是低估了冷迁移的数据量,原以为停机半小时就能把三个月的数据导完,实际 t_comment 一张表就导了四十分钟,远远超出计划窗口,后来改成不停机双写加增量追赶,切换时只差最后两秒的数据。第七个坑是灰度切换的回退演练没做,开关切过去之后发现一个接口在新端有兼容问题,想切回时手忙脚乱找不到入口,之后每次灰度前都先在测试环境演练一遍回退路径,做到十分钟内可逆。
小结
选型这件事,账面差价只是表象,真正决定的是团队能力的形状。而且选型不是一次性决定,我们约定每半年把这张表重算一次,如果哪天自建的曲线越走越陡,也不排除再切回云开发,技术路线服从业务现实,而不是反过来。如果你们的产品有大量定时聚合、缓存语义、长连接需求,自建会更顺手;如果是增删查改为主、人手紧张,云开发性价比其实更高。我们迁移后日活从八千涨到十万,月成本只涨到两千出头,这在纯云开发方案下很难做到。记账方式也推荐学我们做双表对拍,一张算钱一张算能力,再做一次六个月外推,比只看一张表清醒得多。最后说一句过来人的话:选型结论本身没那么重要,重要的是得出结论的过程可复现。我们的整套对拍表格至今还留在团队 wiki 里,每次加新组件就拿出来重算一遍,避免凭感觉做决定。机器规格怎么选、域名备案怎么过,看 轻量服务器建站实战 会更有画面感,多产品组合的成本拆解可以再翻 腾讯云综合实践。
延伸阅读
- Node 建站实战(自建后端的部署参考)
- 腾讯云综合实践(多产品组合的成本账)
- 云开发 Python 实战(云开发方案的另一面)
