近期,我离开了在北京的工作,开始了在英国的新工作和生活。在这之后,我主要在做系统向亚马逊云平台的迁移工作。这个过程中,我遇到了不少问题,但也收获了很多经验。老系统向新平台的迁移,涉及到各种常见的架构组件,需要处理许多细节问题。
1. 缺乏文档: 这是大小公司都存在的问题。详细的文档会极大地降低开发效率,但互联网项目又具有易变和追求速度的特点,因此不太适合做精细的文档。这就要求方案和细节设计上要有合理性,不要做"精巧"的方案。结构化设计,不要零散组成,这样其他人即使没有文档也可以理解。
2. 项目中临时方案太多: 导致后来看起来很别扭,也不容易理解;半截工程。系统中存在大量"精巧"的设计,使后来者难以理解。这也告诉我们,做设计时尽量保持简单通俗易懂,项目设计的可沟通性也很重要。有位工程师说自己花了1周才搞明白Postfix的收邮件并自动解析的过程是怎么运行的。
3. 代码质量参差不齐: 代码质量问题是每个大团队都难以完全保证的。保持代码库的整洁很重要。
4. 繁杂的业务
5. 代码的BUG和代码对环境的兼容性: 之前的系统使用配置文件做主从读写分离,但配置文件存放在代码库中,这意味着代码回滚或check分支出错时,配置文件会发生改变。这导致部分操作写入从库,从库与主库同步失败,出现典型的"脑裂"问题。最后只好花很长时间重做从库同步。这样的问题处理并不复杂,复杂的在于如何发现问题的根源。业务系统各种奇怪的表现,有时很难想到问题的根源。
1. 完善测试: 性能测试可以采用流量镜像复制的方式,读操作有很多简单可靠的流量复制工具,往往不需要高大上的流量复制系统。大部分系统读多写少,测试也不是什么难题。功能性测试只能尽量做足,让熟悉系统的用户进行。
2. 无缝迁移: 整个过程基本实现了平滑无缝迁移,系统没有停止1分钟运行。由于项目特点,比较少写操作,重点是读,暂停写操作后将HaProxy后端逐步指向新集群,等全部流量导入新集群后修改DNS指向新集群。这里还涉及到DNS TTL从长变短再变长的修改过程。缓存预热很重要,尤其是数据库的预热,这就要求新集群流量导入逐步进行,防止对整站延迟的影响。
3. 回退方案: 由于暂时停止写操作,即使流量导入到新集群后测试发现问题,仍然可以指回旧集群。
4. 改进还是保持原状: 由于架构组件的选择余地很大,需要很长时间Review之前各个组件的配置是否合理。这就要权衡保持原状还是一次性做好优化。比较好的方案是,如果不是BUG则保持原状,等系统完成迁移再进行改进。
5. 性能的持续监控和对比测试: 性能监控工具已非常成熟,如AppNeta和New Relic,基本可以把控各个组件的性能。在迁移之前也可以进行镜像流量复制对比测试新旧集群的性能。
1. 重新设计的发布自动化: 业务代码、系统配置、云架构配置的分离,任何操作的版本化,可回退。
2. 弹性扩展,总体成本的降低: 迁移到亚马逊的主要原因就是高低峰流量差异很大。迁移后低峰期可以节约1半的机器成本。
3. 跨区域容灾,无单点故障: 实现了Multi-AZ,任意单点故障不影响业务运行。Web前端服务器可以随手关掉,数据库的升级、配置改动也无任何影响,这归功于RDS Multi-AZ功能。
4. 运维难度的降低,无需运维: 系统会自动根据负载进行增减机器,无需担心压力大导致机器瘫痪,单机器的各种故障也无需人工处理。
关于亚马逊云平台的特点和各个组件,我会在后续文章中详细解释。