某一天,你的公司准备与世界领先的电子商务巨头展开竞争,作为系统架构师,你需要为公司设计一套先进的电子商务应用,应该如何构建它?以你在软件界十余年来的丰富设计经验,很可能会设计出如图1-1所示的应用系统。
图1-1 传统的单体设计的应用系统
你为公司设计了一个庞大的核心应用程序,它包含所有的领域逻辑。其中包括诸如身份、产品目录、订单以及其他模块。这些模块逻辑上是独立的,在物理上这些模块运行在同一个服务器进程中,每个模块都可以直接与其他模块通信。这些模块共享一个大型的关系数据库。应用通过HTML界面或者移动应用展示其功能。
祝贺你!你已经构建了一个 单体应用 。
多年来,单体应用都深受设计师的欢迎,它提供了一些独特的优势。例如,它可以简单直接地进行:
● 构建。
● 测试。
● 部署。
● 排除故障。
● 纵向扩展。
当今的许多成功的应用就是以单体应用的模式构建的。这种类型的应用程序很受欢迎,并且不断发展,通过一次又一次的迭代,还在不断添加更多功能。
不过,到了某个时间点上,你开始感到有点不舒服了。你发现你已经对应用失去了控制。随着时间的推移,这种感觉变得更加紧迫,你不可避免地陷入了称为恐惧循环的状态。
● 应用程序变得非常复杂,以至于没有一个人可以完全理解它。
● 你害怕做出改变——每个改变都有意想不到并且代价高昂的副作用。
● 增加新功能或者修复Bug变得很棘手,耗时且成本高昂。
● 每个版本更新都变得尽可能小,并且需要完全部署整个应用程序。
● 一个不稳定的组件可能会使整个系统崩溃。
● 无法引入新的技术和框架。
● 实施敏捷交付方法变得非常困难。
● 各种不同风格的修补不断侵蚀着架构,应用变得越来越脆弱和难以理解,没有人愿意再继续维护它。
这些是不是听起来很熟悉?这个庞大的单体应用,由于开发人员的更迭,需求的不断变化,慢慢显露出各种疲态。
应用程序本身是有生命的,其潜在的发展趋势是,随着时间推移而变得越来越臃肿,开发团队在每个冲刺阶段都要实现更多的用户需求,这意味着需要添加了许多行的代码。数年之后,小而简单的应用将会逐渐变成一个庞大的单体应用。
一旦产品成为一个庞大、复杂的单体应用,开发团队就会陷入了一个痛苦的境地,对敏捷开发和交付的尝试变得难以推进。主要问题是应用程序变得实在非常复杂,对于任何一个开发人员来说,都显得过于庞大且难以理解。最终,高质量地修复Bug和实现新的功能变得非常困难而且耗时,这种趋势就像是死亡螺旋。如果连最为基本的代码都令人难以理解,那么对软件的改进也就难以保证质量,终将得到的是一个高耸入云但是脆弱的危楼。
应用程序的规模变得越庞大,开发或者运维人员重新启动应用所需要的时间就变得更长。很大一部分时间都将在等待中度过,而这样的时间浪费将会极大的影响和阻碍业务的发展,将开发人员的耐心消耗殆尽,最终将有可能导致公司失去市场机会。
复杂的单体应用本身就是持续部署的障碍。
在当前的技术环境下,SaaS(Software as a Service,软件即服务)应用已经发展到了可以每天多次将变更推送到生产环境中,而这种需求对于复杂的单体应用来说非常困难,因为它需要重新部署整个应用程序,才能完成更新其中的部分功能,同时还需要在应用部署后经过漫长的等待启动的时间,等待应用程序初始化启动完成。
此外,因为难以确认因部署变更所产生的影响,在很多情况下还需要做大量的手工测试。因此,单体应用非常难以与持续部署相结合。
当不同业务模块存在资源需求冲突时,单体应用可能难以扩展。例如,其中一个模块可能会执行CPU密集型的图像处理逻辑,理想情况下是部署在计算能力优化的环境中,而另外一个模块可能是一个内存数据库,它适合部署到更大内存的环境中。然而,由于这些业务模块深度耦合在一起,导致必须在硬件选择上做出妥协。
由于单体应用所有的业务、功能模块都运行在同一个进程中,导致其中任何一个模块的Bug(例如内存泄漏)都有可能会拖垮整个进程,导致应用程序的所有业务都不可用。
单体应用使得采用新的技术框架和语言变得非常困难:假设有一个包含了200万行代码的应用使用框架A构建,想要迁移到新出现的优秀的框架B上,时间与资源成本的消耗是极其恐怖的。
因此,单体应用是采用新技术的巨大障碍,这也导致在项目开始时,无论选择任何新技术都会对整个项目的开发与交付产生巨大的影响。
当一个原来成功的关键业务应用程序,慢慢发展成一个只有少数开发人员(如果有的话)能够理解的巨大单体应用,它还使用了过时的、非当前主流的技术开发,这使得招聘更加优秀的开发人员变得非常困难、应用程序也变得难以扩展、不可靠。
因此单体应用想实现敏捷开发和快速应用交付是不可能的。
通常我们提到微服务就会想到云原生,事实上,微服务与云原生是两个不同维度的概念。
云原生更侧重于应用程序的运行环境,它是以Kubernetes和容器技术为基础打造的一整套工具,用于开发、测试、运行应用程序,直到部署到云环境。
微服务描述的是应用程序的软件架构,微服务是基于分布式计算的架构模式。应用程序即使不采用微服务架构也可以是云原生的,如果是单体式应用,云原生就难以发挥优势。另外微服务的程序也可以不是云原生的。
虽然它们是两种不同的事物,但云原生和微服务是天生的良配,相得益彰,相辅相成。而且很多云原生的工具原来就是针对微服务架构设计的。可以说现代应用程序的趋势就是:“微服务+云原生”。
对于1.1节的单体应用,在运用云原生技术之后,重新设计的系统如图1-2所示。
图1-2 云原生设计的应用系统
图中左边的矩形框表示客户端应用,右边的矩形框是部署在服务器端的服务,这些服务基于容器技术进行部署和管理。
左边的客户端分为三种类型:移动应用,基于Angular技术的单页Web应用和传统的Web应用。
右边服务器端通过多个基于容器技术的独立微服务来实现,它们之间通过事件总线彼此协作。这些服务以API的方式对外暴露其功能,中间的API网关将这些服务进行组合,对外显示为针对不同客户端的API服务。
业内一般公认云原生概念是在2013年首次提出的,由Pivotal公司(Spring开源产品的母公司)的技术产品经理Matt Stine在推特上提出。
2015年,Matt Stine在其编写的《迁移到云原生应用架构》
中,率先提出了将传统的单体应用和面向服务架构(Service-Oriented Architecture, SOA)的应用迁移到云原生架构所需的文化、组织和技术变革,并定义了云原生应用架构的几个主要特征。
● 十二要素应用程序:云原生应用程序架构模式的集合。
● 微服务:独立部署的服务,每个服务只做一件事情。
● 自助服务的敏捷基础设施:快速、可重复和一致地提供应用环境和后台服务的平台。
● 基于应用程序接口(Application Programming Interface, API)的协作:发布和版本化的API,允许在云原生应用架构中的服务之间进行交互。
● 抗压性:系统具备良好的健壮性,能够抵抗外界非预期的流量冲击。
CNCF
的全称是Cloud Native Computing Foundation(云原生计算基金会),成立于2015年,是Linux基金会旗下最大的开源基金会,也是目前Linux基金会下最受关注和发展最快的基金会。它的初衷是围绕云原生,服务云计算,致力于培育和维护一个中立的开源生态系统,维护和集成开源技术,支持编排容器化微服务架构应用,通过将前沿的模式开放化,让这些创新为大众所用,从而助力企业在云计算模式下更好的构建可扩展的应用程序。如图1-3所示的云原生全景图就是来自于CNCF。
图1-3 CNCF云原生全景图
作为全球云原生应用特别是容器计算、微服务等技术领域最具影响力的组织,CNCF提供了一个中立的合作平台,汇聚全球顶尖开发人员、终端用户和厂商,联合了华为、阿里、腾讯、亚马逊、微软、Salesforce等近千家国际知名科技公司,共同努力打造一个良性发展的云计算生态。全球主流的科技企业和云计算厂商绝大部分都是CNCF会员,其中不乏多家来自中国的科技巨头
,如图1-4所示。
图1-4 CNCF中来自中国的科技巨头
截至本书完稿,CNCF旗下共有145个项目,18.2万名贡献者,863个组织
。
结合图1-4仔细研究这组数据,就会发现CNCF的成员几乎涵盖了所有的云原生相关的组织和项目。