4.8 标准化
4.8.1 规范可重复
以构建为例,我们希望只要是同一份源代码,不论什么时候构建,构建出的安装包都是一样的。也就是说,系统运行起来都有相同的功能和性能。类似地,同一份源代码,不论在哪里构建——是在开发人员的笔记本电脑上构建,还是在构建服务器上构建,构建的结果也应该相同。为此需要保证,构建使用的工具版本总是相同的;构建使用的方法和命令参数总是一样的;构建时下载的各个依赖包总是来自同一个制品库,内容也不会发生变化。
事实上,不仅当源代码版本不变时,我们期望构建过程总是标准的、可重复的,而且当这份源代码不断演进时,我们也期望构建过程总是标准的、规范的,除非要明确地改变该规范。
类似地,我们希望分支的命名、版本的命名、文件目录结构等都遵从一定的规范,让人易于理解和查找,同时也方便机器自动处理。“约定优于配置”是构建工具Maven的核心理念之一,其正是反映了我们对规范性的期待。
那么,如何做到可重复?常见的思路是代码化、纳入版本控制中,然后自动化执行。如何做到规范?可以通过宣讲、考试等方法来提高人员的能力,而如果能够把规范内化到工具中,在违背规范时自动提醒或者根本就没有违背的机会,那就更好了。
4.8.2 方案收敛
前面讲过,对于同一个代码库、同一个微服务,我们应该总是使用相同的工具、方法和流程。其实,对于不同的代码库、不同的微服务,不同的开发团队甚至整个公司也应该尽量使用统一的工具、方法和流程。
这样做一方面可以降低学习成本。人员在不同的代码库、不同的开发团队之间流动时,不必重新学习相关知识。此外,不同的团队相互协作时,也好配合。
另一方面也降低了工具、方法和流程的制定、开发、维护的成本与风险。例如,如果每个团队都搭建一套版本控制服务,那么每个团队都要进行方案比选、购买(如果是付费产品)、开发或定制(如果有自研的部分)、运维、版本升级等,这实在没必要。
当然,不同的开发团队、不同的系统,其规模、对质量的要求、产品所处的阶段都可能是不同的。因此,其所适合采用的工具、方法和流程也可能有所区别。所以可以提供几种不同的模式和选项供团队选择,也允许先试点,做一些尝试。总之,要避免没有必要的“百花齐放”,适当收敛。
4.8.3 环境一致性
当在测试环境中进行测试后,我们希望被测对象在生产环境中能毫无问题地运行起来。而当生产环境中出现问题时,我们也希望在测试环境中能容易地复现问题。因此,我们希望各个运行环境之间尽可能相像。
为此,要有机制保证各个环境中的程序所在的本机环境,也就是操作系统版本、本机预先安装的各个软件、相应的配置等,应该是一致的。根据相同的容器镜像生成各个环境中运行的容器,就容易做到这一点。
除了本机环境,各个运行环境中所使用的数据库服务、消息队列服务、远程调用服务等中间件服务及其配置,也应该尽可能相同。
而测试环境中的各个微服务的版本,也应该尽可能保持与生产环境相同。当然,本次改动的微服务应该部署改动后的版本。
在测试环境中常使用Mock、挡板等方法来应对整体系统中的一部分无法提供或不稳定的情况。例如,当这部分是由其他部门提供的甚至是外部系统时,则至少应该在发布上线前,在真正的整体系统中做一次端到端测试。如果想做得更好,则应该尽可能早地在真正的整体系统中进行测试,为此需要在各个测试环境中尽可能实现整体系统并保持其稳定。
从部署的角度来看,部署不同的环境应该使用相同的部署工具,遵循相同的过程。当然,在滚动部署时分批进行之类的设置是可以不同的。
综上所述,不同的环境如测试环境与生产环境之间要尽可能相像。而在一个环境内部,当一个微服务有多个实例同时运行时,它们之间也要尽可能相像,这主要体现为各个运行实例所在的本机环境之间要尽可能相像。前面提到的根据相同的容器镜像生成运行的容器这种方法,对解决这个问题同样很有帮助。