如何部署微服务
1. 持续集成CI
CI能够保证新提交的代码和已有代码进行集成,从而让所有人保持同步。CI服务器会检测到代码已经提交并签出,然后验证代码是否通过编译以及测试能否通过
1) CI的好处
1. 代码质量的快速反馈
2. 自动生成二进制文件
3. 所有代码均在版本控制之下
4. 从已部署的构建物回溯到代码
5. 测试自动话
2) 是否真正在做CI的三个问题
是否每天签入代码到主线?
即使只使用生命周期很短的分支来管理这些修改,也要尽可能频繁地把代码检入到单个主线分支中,否则将来的集成会非常困难
是否有一组测试来验证修改?
验证系统的行为是否已经被破坏,没有对代码行为进行验证的CI不是真正的CI
构建失败后,团队是否把修复CI当作第一优先级?
绿色的构建:修改已经安全地和已有代码集成在了一起
红色的构建:最后一次修改很可能有问题
2. 微服务的持续集成方式
1) 把所有微服务放在同一个代码库中,并且只有一个CI构建
也叫同步发布(lock-step release)
优势:a. 开发者的工作得到简化,只需提交代码,如果需要在多个服务上工作,一个提交就能搞定;b.关心的代码库比较少
劣势:a. 仅修改一行代码,在代码库里的所有其它服务都要进行验证和构建,实际并不需要。如果该行代码修改导致构建失败,那么在构建得到修复之前,与其它服务相关的代码也无法提交;b.影响单个修改从开发到上线的速度及CI的周期事件;c.退回到同时部署所有代码的模式
建议:应该避免这一模式
例外:当仅有一个团队在所有服务上工作时,这种模式短期内是可以接收的;项目初期,需要花很长时间识别服务的边界,在识别出稳定的领域之前,可以把初始服务都放倒一个代码库
2) 将一个代码库的子目录映射到不同的构建中
优势:简化检出/检入的流程
劣势:会让开发者认为同时提交对多个服务的修改是件容易的事情,从而做出将多个服务耦合在一起的修改
建议:尽量不采用
例外:如果代码库的目录结构定义得合理,就会很容易把其中一部分映射到一个构建中
3) 每个微服务有一个源代码和CI构建
优势:a.代码库与团队所有权的匹配程度高,团队应该对服务、代码及构建负全责 b.当对代码库进行修改时,可以只运行相关的构建以及其中的测试。C.容易知道应该运行哪些测试:每个与微服务相关的测试也应该和其本身的代码放在一起。
劣势:跨微服务做修改会比较困难(可以考虑使用命令行脚本解决)
建议:当服务的API稳定之后,可以开始把它们移动到各自的构建中。
3. 微服务的持续交付(CD)方式
持续交付(Continuous Delivery,CD)检查每次提交是否达到了部署到生产环境的要求,并持续反馈这些信息,还会把每次提交当成候选发布版本来对待。CD对多阶段构建流水线的概念进行扩展,从而覆盖软件通过的所有阶段,无论是手动还是自动。
1) 自动化配置管理工具
在技术栈里只有构建物是不够的,还需要安排和配置其它一些软件,然后再启动这些构建物。
优势:自动化配置管理工具可以对不同构建物的底部部署机制进行屏蔽。Chef、Puppet及Ansible都支持一些通用技术栈的构建物部署
劣势:a. 需要花费大量时间运行Chef、Puppet、Ansible等自动化配置工具的脚本 b.配置漂移(机器上的实际配置和源代码管理中的配置不再一致)
2) 操作系统构建物
RedHat/CentOS: RPM
Ubuntu:deb包
Windows:MSI
优势:在做部署时不需要考虑底层使用什么技术,只需要简单使用内置的工具就可以完成软件的安装、卸载和查询,甚至还可以把CI生成的构建物推送到软件包仓库中。
劣势:a.刚开始编写构建脚本的过程比较困难。Linux的FPM包管理工具提供了很好的抽象,Windows的NuGet简化了开发库的依赖关系。b.部署到多个操作系统,维护不同版本的构建物的开销会很大
建议:如果软件是部署到自己可控的机器上,最好只维护一种操作系统
3) 定制化镜像
3。从运行的实例烧制镜像
优势:只需构建一次镜像,不需再花时间来安装相应的依赖,如果核心依赖没有改变,新版本的服务可以继续使用相同的基础镜像
劣势:a.构建镜像会花费大量的时间
b.产生的镜像可能很大
c.构建不同的平台上的镜像所需的工具链不一样
4) 不可变基础设施
原则:
a. 禁止对任何运行的服务器做手动修改。
b. 无论修改多么小,都需要经过构建流水线来创建新的机器。
实践:
a. 把镜像作为构建物,服务放在镜像里,当镜像启动时,服务就已经就绪了。
b. 在镜像的创建过程中禁止SSH,以确保没有人登录到机器上做任何修改
c. 持久化数据要保存到其它地方
4. 微服务部署的环境
微服务构建物在软件的生命周期是一样的,但是环境不同,至少它们的主机是隔离的,配置也不一样
微服务的配置单独管理,配置的形式可能是环境的属性文件,或者是传入到安装过程中的一些参数
5. 服务与主机之间的映射
1) 单主机多服务
优势:
a.从主机管理的角度来看它更简单,在一个团队管理基础设施,另外一个团队管理软件的模式下,管理基础设施团队的工作量通常与所要管理的主机量成正比。
b.关于成本:虚拟化的基础设施本身也会占用一部分资源,从而减少服务可用的资源。
c.简化开发人员的工作,将多个服务部署在生产环境的单个主机上,与把多个服务部署在本地开发机器上的过程很类似。
劣势:
a.监控变得更加困难。如当监控CPU使用率时,应该监控每个单独的服务还是整个机器?
b.服务之间的影响不可避免:一个服务的负载很高,那么它有可能会过多占用系统其它部分的资源
c.服务的部署也会变得更复杂。很难保证一个服务的部署不会影响到其它的服务。如:每个服务的依赖不同(甚至有可能是冲突的)该如何处理?
d.对团队的自治性也不利。如果不同团队的服务安装在同一台主机上,那么很可能需要一个专门的t
e.限制部署构建物的选择
f.增加对单个服务进行扩展的复杂性。
建议:违背了微服务单独部署的原则,不建议采用
2) 应用程序容器
优势:
a.使用容器来简化管理,比如对多实例提供集群支持、监控等。
b.节省语言运行时的开销。比如,在一个Java servlet容器中部署五个Java服务,只需要启动一个JVM
劣势:
a.不可避免地限制技术栈的选择。只能选择一种技术栈。
b.限制自动化和系统管理技术的选择。
c.限制容器的可伸缩性:容器通过集群管理来支持内存中的共享会话能力
建议:使用自包含的服务器构建物。对于.Net来说,类似Nancy。对于Java,Jetty嵌入式容器使用了一个非常轻量级的自包含HTTP服务器。
3) 每个主机一个服务
优势:
a.简化了监控和错误恢复
b.减少了潜在的单点故障
c.采用一些不同的部署技术
劣势:
a.管理更多的主机会引入隐式代价
建议:引入PaaS,结合自动化
6. 统一部署接口
从本地开发测试到生产环境部署,不同环境的部署机制应尽量相似。
参数化的命令行调用是触发任何部署的最合理的方式
环境定义的例子:
网友评论