Vercel, Cloudflare, fly.io 我的云服务三剑客

Update: 在排查 Cloudflare 缓存命中率低的问题时,发现没有一台 Server 实在是不方便。比如想看下哪些请求透过了 CF,直接到了源站,如果内容 deploy 在 Vercel 上,就看不到这些请求日志。所以虽然 Vercel 很方便,用起来也很舒服,但一些能力上的缺失在某些场景下还是挺难受的,因此还是转向了 VPS(Vultr) + Cloudflare 的传统配搭。

自己时不时地会写一些网页(如 拼音猜成语)或部署一些静态页面(如这个博客),或者托管一些资源文件(如播客音频),这就涉及到线上服务的选择。目前来看 Vercel, Cloudflare 和 fly.io 能较好地满足我的大部分需求。

DNS 管理 & CDN

这部分交由 Cloudflare(简称 CF) 来管理。在 CF 后台新建 Site 后,在域名注册商处,将 Name Server 设置为 Cloudflare 的 Name Server 就行了,就是下面这两个

  leah.ns.cloudflare.com
wesley.ns.cloudflare.com
CF 也提供域名注册服务,如果是新的域名,可以直接在 CF 注册,管理起来更方便,价格也不贵。

因为 CF 的主营业务还是 CDN,所以提供了一个很方便的功能:代理网站静态资源,也就是这朵橘色的云(Proxy Status)。

开启了之后,domain 下的资源(如图片,CSS 等)会被 CF 缓存到 CDN,用户访问这些资源时,就直接访问 CDN 上的缓存,不会到自己的服务器,可以节省很多流量。而且 CF 的 CDN 流量是免费的,所以不用担心哪天站点访问量剧增带来的流量费用。

PS: 开启「自动代理」后,如果出现直接访问 OK,但通过 CF 访问就会出现问题的现象,可以把 SSL/TLS 设置为「灵活」。

Vercel, Cloudflare, fly.io 我的云服务三剑客_第1张图片

如果发现 CF 访问统计中,有很多的流量没有缓存,可能是跟 Vercel 返回的 Cache-Control 有关,比如 Cache-Control: public, max-age=0, must-revalidate,表示不缓存,这样 CF 也要遵从这个约定,当用户访问资源文件时,如果浏览器本地没有缓存,或者已经过期,每次请求到了 CF 这里后,CF 也还是要到源站(Vercel)去取。这样不仅没有让 CF 发挥 CDN 的优势,反而因为要回源,导致请求变慢。

好在 Vercel 支持自定义 header 规则(更多的规则可以看 这里),我们可以在 vercel.json 里重新定义 Cache-Control

  {
  "headers": [
    {
      "source": "/(.*).(jpe?g|png|ico|webp|svg|mp4|gif|xml|ttf|woff2?)",
      "headers": [
        {
          "key": "Cache-Control",
          "value": "public, max-age=31536000, immutable"
        }
      ]
    }
  ]
}

这样当访问特定后缀的资源文件时,就会返回我们定义的 Cache-Control,CF 会根据新的 Cache-Control 策略来缓存,比如这里设置了永不过期。

PS: Vercel 有个 页面专门讨论了与 CF 并存的问题,想进一步了解的话,可以看一下。

PPS: 这么做确实可以达到效果,但 CF 后台显示缓存命中率只有不到 10%,需要进一步排查。

CF 默认不缓存 HTML 文件,如果要设置更加灵活的缓存策略,可以通过 Page Rules 来完成,免费用户可以设置 3 个规则,基本够用了。

Vercel, Cloudflare, fly.io 我的云服务三剑客_第2张图片

还有一个好处是,可以在 CF 的后台看到页面的访问统计,虽然比较简单(能看到访问次数,但无法精确到页面,或者来源),但不需要额外的 JS 代码,不用依赖第三方访问统计服务,也还不错。

CF 还可以托管一些存储服务的文件,以 Backblaze(又称 B2) 为例,对 DNS 的 CNAME 做一下映射(同样要将 Proxy 设置为 Proxied),比如将 assets.example.com 映射到 f002.backblazeb2.com,通过后台或 API 上传资源文件(如播客的音频)后会得到 B2 的 URL,将域名换一下就行了。比如将 https://f002.backblazeb2.com/a/b.mp3 替换为 https://assets.example.com/a/b.mp3,就可以使用 CF 的 CDN 服务了。

静态页面

通过 SSG(静态内容生成器)生成的博客或文档等静态资源,会部署到 Vercel 上,体验确实很不错。比如 Connect Github 后,做一些简单的配置,就能方便地 Deploy 了。push 到 main 之外的分支,可以生成 Preview 页面,确定内容正确后,再 push 到 main 分支,就上线了。这也是 Vercel 提倡的 Develop, Preview, Ship 流程。

每个月 100 G 的流量(所有 Projects 加起来)如果都走 Vercel,可能不太够,但结合 CF 就完全能 hold 住了(流量主要是一些 HTML 页面)。

如果要写一些复杂的页面或涉及到一些后端逻辑,也可以使用 Vercel 开源的 Next.js。API 会以 Serverless 的方式运行(所以不要依赖一些内存全局变量)。最近 Middleware 也 GA 了,可以在请求到达具体页面前再做一些处理(比如判断是否有特定的 Cookie,然后重定向到特定的页面)。

CF 也提供类似的服务 Cloudflare Pages,不过目前对 Vercel 还比较满意,就没考虑切换。

动态数据

如果涉及到数据库,对个人项目来说,要么在单独的 VPS 上部署,要么在 Serverless code 里通过 API 去连接 Cloud Database Service,前者有一定的维护成本,要保障 VPS、后端服务、DB Service 的正常运行,还要考虑各种运维(网络耗时、磁盘空间、CPU、内存占用等等),后者就要找一个合适的服务商,确保价格、空间、流量、使用体验等比较满意。

其实也可以有第三种选择,我选的是 fly.io,可以简单地理解为把 Docker 部署到边缘节点,让用户可以就近访问服务。fly 的免费版本提供了一定的存储空间(3GB,先创建 Volume,然后 mount 到 App 上),一些简单的项目,一个 SQLite 文件就搞定了,备份起来也很方便。更 Serious 的项目可以使用他们提供的 Postgres 数据库(支持多节点部署,读写分离)。

这样就兼具了 VPS 的灵活性,又免去了不少运维成本,又因为服务可以部署在全球的各个节点,访问速度上也比较有保障(挂了 Volume 后,就只能锁定单个区域,因为 Volume 跟 App 和 Region 绑定)。

目前只是在上面部署了一个小项目,还没有较正经地使用,不过有 Remix 和 Kent 的背书,从一些 其他的反馈来看也还可以,应该会是不错的选择。

还有一个原因是 fly.io 给我的感觉也是满酷的,比如 Rust 开发的招聘文,这是其中一段:

The premise of our hiring process is that we’re going to show you the kind of work we’re doing and then see if you enjoy actually doing it; “work-sample challenges”. Unlike a lot of places that assign “take-home problems”, our challenges are the backbone of our whole process; they’re not pre-screeners for an interview gauntlet.


这三家服务商基本覆盖了我所有的线上需求,而且只需支付很少(或者免费)的费用就能支撑足够大的访问量(Cloudflare 功不可没)。如果你也有类似的需求,或许可以考虑下。

你可能感兴趣的:(vercel,cloudflare,fly)