系列专栏声明:比较流水,主要是写一些踩坑的点,和实践中与文档差距较大的地方的思考。这个专栏的典型特征可能是 次佳实践,争取能在大量的最佳实践中生存。

一、基于 Midway 的基础设计

一些概念参见 部署架构设计

  1. 关于 FC,没有选型 Custom Container ,因为冷启动太明显了,耗时和干脆 504 频率太高,除非维持一个长期的兜底热容器,否则天生无法解决
  2. 关于 Midway,没有选型自带的 npm run deploy 模式,而是 npm run package 后将 serverless.zip 传到了 OSS 制品仓库,是因为在现阶段 git commitbuild artifact 还能难做到一一对应,实践上还是要以 build 为准;典型的场景是事故回滚,重新部署一个 build 是比较有信心的,而指定一个 git commit 再执行一次 build 是没有信心的
  3. index.htmlrsrc 是同一个 制品,体现在这个架构图上,即都被打包到了 serverless.zip 中,也即访问 https://app.../index.htmlhttps://app.../rsrc/ 能够访问到相应的文件;但是我们会使用一个名为 rsrc.cdn 的配置项,指定用户去访问 https://cdn...

    <!-- template -->
    <html>
      <body>
        <div id="root"></div>
        <script src="{rsrc.cdn}/rsrc/dist/umi.js" />
    
    <!-- profile=local -->
    <html>
      <body>
        <div id="root"></div>
        <script src="http://127.0.0.1:3000/rsrc/dist/umi.js" />
    
    <!-- profile=prd -->
    <html>
      <body>
        <div id="root"></div>
        <script src="https://cdn.../rsrc/dist/umi.js" />
  4. 理论上,应该将制品中的 public 这个文件夹上传到 bucket-cdn,但这样就需要实现相应的授权 upload 流程,所以这里采用了回源模式:

    1. 北京用户访问 https://cdn.../rsrc/dist/umi.js,北京城市节点没有,于是向 oss/bucket-cdn 回源
    2. 对于第一次访问,oss/bucket-cdn 也没有,于是向 http://app-vpc.../rsrc 回源;此时会启动一个 FC,oss/bucket-cdn 于是得到了这个文件,并顺请求的原路返回给北京用户
    3. 上海用户访问 https://cdn.../rsrc/dist/umi.js,上海城市节点没有,于是向 oss/bucket-cdn 回源,这次有了,所以不用继续向上回源,可以直接返回
    4. 以上每个请求都会独立的唤起一次 FC(不考虑云厂商智能复用的情况,作为开发者我们需要把这里设计为无状态的),即 index.html / umi.js / umi.css 会唤起 3 次 FC
    5. 当 CDN 热身完成后,只有每次请求 index.html 会唤起 1 次 FC

二、Vercel 存在的问题

以上这个模型是完备的,但还缺最后一公里。阿里云的 FC 目前没有 Edge(文档上似乎有内测,但感觉还不能用),因此所有请求到 index.html 都必须由杭州的 FC 来承担。

对于其中 SSG 的部分,比如 index.html,我们可以使用类似 cdn 回源的方式部署到阿里云各城市节点上,但这需要自己设计和实现。Vercel 是原生支持的。对于其中 SSR 的部分,比如 account.html,目前只能通过唤起杭州的 FC,Edge Script 离能用还有一段距离。而 Vercel 也是原生支持的。这就是云原生生态的力量,并不是实现了每个粒度的功能让开发自己去组合,而是直接按照开发 应有 的行为去提供一个整合的 产品。这里的确损失了自由度,但这些自由度本来就是开发所不需要的,开发应该聚焦在交付业务功能上。

Vercel 非常激进的基于 GitOps,严格由 Git Commit 来触发发布,从而导致缺少了 制品 这个概念。这会带来两个问题,一是由于 IaaC 很难完整实施,Commit 对依赖的管理并不能完全锁定,所以对同一 Commit 的再次 Build 并不能得到 Immutable 的结果,这样回滚还不如向后修复(当然,在敏捷的开发文化里确实只有向后修复,也许这在 Vercel 的生态里不是问题)。

第二个问题是,Vercel 上永远只有最新版的代码,这样如果客户端有缓存,那么去访问上个版本的资源时就会失效。无论开发文化多么敏捷,这样对待客户体验的方式是不对的。如果在现有的 Vercel 上要解决这个问题,就必须和 App 一样执行语义版本,将语义版本和 Build 版本统一,即使用 /index-1.0.html + /rsrc/dist-1.0/umi-1.0.js。这个实践对开发尚且有难度,对运营则是完全不可能的,当链接地址投放出去以后,比如打印到了海报上,是物理上不可能升级的。Vercel 这种纯线上的风格,在落地时是行不通的。

三、组合使用 Vercel 和 Midway FC 的改进

解决的方案比较粗糙,演示意义大于实践意义,从生态上看,应该是由 Vercel 和 FC 各自去完善自己的产品。

感觉就差一个可观测性,这个系列的文章就闭环了。

Vercel 真的是太快了

vercel-fast.png

参考文献

  1. 如何评价 CSS 框架 TailwindCSS
  2. Umi 开发一个 Blog (这是一个 CSR 的示例,所以其实并不典型)
  3. Midway 静态网站托管 (可以看出来确实没有 Vercel 那种同时支持 SSG 和 SSR 的能力;但实际上阿里云送的域名与服务的路由绑定可以实现这个映射,将 SSG 和 SSR 部署为两个独立的服务就好)
  4. Next.js File Structure

理斯特
18 声望9 粉丝

web/mobile/iot, front/back, js/java