我们为什么把 Mythex 的服务器迁移到 ARM
9 月 19 日,我们将 Mythex 的生产后端从 x86 服务器迁移到了更小的、基于 ARM 的 AWS Graviton 服务器,同时把平台数据库也迁移到了 Graviton 实例。触发这次迁移的原因很简单:在我们把重负载工作——运行和构建每个用户的应用——转移到相互隔离的各项目沙盒之后,我们的主服务器内存峰值只有大约三分之一。更小的 ARM 机器完全能满足实际负载,并将每月服务器账单降低了约 30%。
我们的服务器现在做什么
早先,后端服务器直接承担了大量工作。大约在 9 月中旬,我们完成了把开销最大的部分——运行每个项目的代码、安装依赖包、构建应用——迁移到私有云沙盒中的过程,每个项目一个沙盒。这也正是每个项目获得独立隔离环境和实时预览的原因。
留在我们自己服务器上的,是协调类工作:API、管理沙盒和发布的编排器、身份认证、计费和网关。这类工作稳定且轻量。迁移之后,服务器的内存峰值约为 1.3 GB,而机器本身有大约它三倍的内存。
为什么选择 ARM
AWS 的 Graviton 处理器是由 AWS 自行设计的 ARM 芯片。同样的价格,通常可以获得比同类 x86 实例更多的算力,或者以更低的价格获得同样的算力——而对于我们这样的工作负载(Node.js 服务、Docker、Postgres),没有任何东西把我们绑定在 x86 上。
我们迁移了:
- 两台应用服务器,从中等规模的 x86 实例迁移到各带 2 GB 内存的小型 Graviton 实例。
- 平台数据库,从一台小型 x86 数据库实例迁移到其对应的 Graviton 版本。
唯一的真正麻烦:两种架构的镜像
我们的预发布环境仍然运行在一台小型 x86 服务器上,而生产环境现在运行 ARM。为一种架构构建的容器镜像无法在另一种上运行。
因此,现在每个镜像都会在同一个标签下为两种架构分别构建——即多架构镜像。Docker 会在每台机器上自动选择正确的变体,部署流水线也无需知道它正在推送到哪个环境。代价是 CI 构建时间变长;收益是预发布和生产运行的是完全相同的代码,来自完全相同的标签。
迁移前规划回滚
在一项正在运行的服务上更换 CPU 架构,是你希望能在几分钟内撤销的变更。切换之前,我们:
- 保留了之前的服务器模板版本,作为一个命名的回滚目标;
- 在调整数据库大小之前,立即为数据库做了快照;并且
- 编写了一份运行手册,涵盖迁移过程以及回退的方式。
我们最终没有用到回滚。但下次我们仍会以同样的方式来做。
我们会关注什么
较小的服务器余量也更小。由此产生两点注意事项:
- 如果重负载工作再次迁回这些服务器,2 GB 将不够用。 届时的解决办法是换用更大规格的 Graviton 实例,而不是回到 x86。
- 小型机器需要交换空间。 一周之后,其中一台服务器就因内存压力而冻结,但并没有真正耗尽内存——参见缺失交换文件的故事。
我们的收获
- 架构变化之后要重新测量。 把工作迁移到沙盒改变了我们服务器的需求;而实例规格并没有跟上这种变化。
- 只要镜像是多架构的,对于典型的 Web 技术栈来说,ARM 是一项低风险的收益。
- 先写好回滚方案。 即使你从未用到它,它也能让变更过程更加从容。