...
Back

我们在一周内换了三次托管平台

先是云函数,然后是 PaaS,最后是容器运行时。每一次搬家都有正当理由。但我们一开始该衡量的不是价格或功能清单,而是「这个平台我得在脑子里装下多少」。

我们在一周内换了三次托管平台

我们在一周内换了三次托管平台 🚚

一周之内,我们的部署目标从云函数搬到 PaaS,再搬到容器运行时。每一次的理由单看都站得住,合起来看很难为情 —— 而这整段弯路,源于我们在错误的维度上比较平台。


每一次尝试真正教给我们的

云函数。 吸引力是真的:不用估算服务器规格、可以缩到零、按请求计费。问题在于,一个带路由层的服务端渲染应用不是一个函数。要让它跑起来,就得把每个请求交给函数内部的框架请求处理器 —— 那就是框架的服务端,跑在一个被设计成"不是服务端"的东西里面。内存和超时都得远远调过默认值,页面才能稳定渲染。到那一步,我们是在用函数的价格买服务端的行为,却没有服务端的手感。

我们忽略的信号:当修法变成「把限制调高到它不再像个函数为止」,说明抽象选错了。

PaaS。 契合度好得多 —— 它要一个 Dockerfile,它也确实把它构建并跑起来了。这次我们输在构建缓存行为上。chore: 不用缓存强制重建 在我们的历史里出现过不止一次,这是个信号:我们不理解平台什么时候复用层,于是开始乱捅它。便利性抽象一直很舒服,直到你需要确切知道刚才发生了什么的那一刻 —— 然后你就在通过一个日志查看器调试别人的启发式规则。

容器运行时。 我们留下的地方。不是因为它客观最好,而是因为它的心智模型很小:这是镜像、这是端口、这是几个实例。搬过去之后的每一次失败都是我们自己的失败,在我们自己的 Dockerfile 里,本地可复现。


我们本该用的那个维度

我们比的是价格、区域可用性和功能清单。这些都要紧,但它们不是那一周的成本来源。真正的成本来源,更准确的说法是:

凌晨两点排查一次糟糕的部署时,我得在脑子里装下这个平台的多少?

姑且叫它模型大小。容器运行时的很小:镜像、端口、环境变量、并发、实例数。PaaS 的更大,因为它的那些便利 —— 推断出的构建步骤、缓存启发式、自动的服务接线 —— 都是你没写、也没法逐步跟踪的行为。函数的模型也小,但对一个有状态的服务端来说不合身,这是另一种昂贵。

小模型胜过功能数量,理由很具体:功能在选购时是可见的,模型大小只在出事时才可见。你恰好在最付不起的时候感受到它。


真正能预测痛苦的几个问题

如果重做一次评估,清单是这样:

  1. 我能在本地逐字节复现生产构建吗? 如果平台的构建方式和我不一样,那每一次构建失败都会变成一次远程调试。光这一个问题,就能把我们那三个候选排出正确顺序。
  2. 冷启动会发生什么,我能花钱避开吗? 不是"快不快",而是它是不是一个我能控制的旋钮。缩到零是一个成本决策,它应该是决策,而不是属性。
  3. 日志去哪儿了,我能按请求检索吗? 聚合面板是用来看曲线的。排查需要的是一个请求从头到尾的完整故事。
  4. 怎么回滚,要多久? 诚实版本:从"这坏了"到"上一个版本已经在线"之间有多长。如果答案里包含重新构建,那就不是回滚。
  5. 构建上下文是什么,哪些东西是构建期烘进去的? 任何被内联进客户端产物的值都在构建期就定了。如果平台替你构建,你必须确切知道它是用哪套环境变量构建的。

三者各自值得留下的

这里没有对平台的判决。函数运行时对真正的函数极好 —— webhook、定时任务、图片缩放。PaaS 确实能比任何东西都快地把一个小服务弄上线,而对一个永远不需要知道缓存干了什么的项目,这是实打实的收益。容器运行时前期要你付出更多,回报是可预测性。

错误不在于连错三次,而在于我们按选购页的维度做选择,而真正要紧的维度是:部署出事时,我们得逆向工程多少别人的行为。