经过与开发人员、架构师和 DevOps 工程师的持续沟通,我们了解到他们对于当前应用的设计和构建现状感到不满。他们厌倦了在不同云之间费力地迁移应用,不停地快速新增额外的计算基础架构来满足不期而至的需求,或在遭受重大故障或中断后努力恢复运行。从根本上说,传统应用架构所带来的压力和麻烦令他们筋疲力尽。
我们的客户和社区成员再三表示,他们希望构建“现代应用”。“现代应用”的含义十分宽泛,不同的人有着不同的看法,所以我们询问了我们的开发和 DevOps 同事他们眼中的现代应用是什么样的。我们想要为“现代应用”下一个明确的定义(其中包含现代应用所需的所有关键要素),以便在未来的应用开发和设计工作中用作检查清单和参考点。
本文从某种程度上是 Thomas Wiggins 开创性文章“十二要素应用宣言(The Twelve Factor App)”的延伸。事实上,Wiggins 提出的几乎所有观点仍然以某种形式适用于当今环境。但应用环境经过发展,已包含容器、API 和真正的分布式计算等新技术。云原生计算基金会 (CNCF) 还制定了宏伟的应用愿景,包括极其实用的 Trail Map 路线图。该路线图概述了云原生应用(包括容器、CI/CD、服务网格、可观察性及分布式数据库)的各个层面和一些架构考虑因素。
我们希望在这些强大的基础之上进行定义,为开发人员、架构师和 DevOps 工程师提供应用设计和部署基准。我们在创建该定义前对应用开发模式进行了长达数月的内部讨论,并在定义之后继续与我们的客户和社区成员进行讨论(在创建该定义前,我们对应用开发模式进行了长达数月的内部讨论;并且,在创建定义之后,我们仍继续与我们的客户和社区成员进行讨论)我们认为,“现代应用”的定义分为两部分:四个高层概念以及支持这些概念的六大原则。
现代应用的四大支柱(八大风格)
在我们的研究过程中,许多人都表示,现代应用必须具备可扩展性、可移植性、弹性和敏捷性等关键属性,我们将其称为“现代应用的四大支柱”。这些术语很常见,并且十分流行。我们需要针对当前云计算日益盛行,客户连接无处不在的现实,从应用设计的语境来定义这些术语。
支柱 1:可扩展性
可扩展性包含两个要素:计算容量的扩展和速度的扩展。这两个要素可能相互依赖,并且解决相同的问题。我们在“快速扩展”和“长期扩展”的语境下来认识这两个要素:
-
快速扩展 —— 能够在 5 分钟内将应用容量增加一倍。能够在如此短的时间内将容量翻倍意味着应用可以快速扩展容量,以满足大多数不可预见的需求增长。大多数云实例及其组件工作负载的启动时间大约为 5 分钟或更短。因此,5 分钟意味着现代应用在设计上支持立即扩展,并考虑了基础架构层的限制。
-
长期扩展 —— 能够在一年或更长时间内将应用容量扩大 10 倍,而无需对代码进行重大重构或对基础架构进行重大调整。支持“长期扩展”的现代应用是简洁设计的产物,与基础架构组件保持松散依赖和松散耦合。简而言之,现代应用的大规模可扩展性是内置而不是附加的。
支柱 2:可移植性
在当今“云时代”,企业一直梦想着 DevOps 团队能够轻松地在不同的云之间迁移应用,并期望应用能够平稳地运行。而现实与梦想之间有着很大的差距。虽然容器在当今得到了广泛使用,但由于各个云之间的差异(依赖关系、工具、配置细微差异等),企业无法在向混合多云架构迁移时实现即时可移植性。例如,GCP 的负载均衡器和数据存储特性可能不同于亚马逊云科技或 Azure 的特性。在此,我们提供了一个更现实、更合适的可移植性定义。
-
功能可移植性 —— 无论应用的运行环境如何,其核心功能元素、代码和逻辑必须保持不变。这意味着您的代码在容器内干净地运行,没有与单个环境紧密耦合的外部依赖项。通过这种设计,DevOps 团队能够更干净地移动应用或在多个云中启动正在运行的应用的实例,而不必担心核心应用的逻辑和要求。
-
管理可移植性 —— 应用的管理元素与环境无关,包括可观察性、安全性和监控。无论运行环境如何,支持以相同的方式(使用相同的工具和相同的报告功能集)监控、保护和观察应用。管理可移植性可能需要应用设计人员能够清晰地划分这些关键功能,以免利用公有云的默认服务或产品。虽然最初会有所不便,但现代应用的管理可移植性设计对于实现其他三个支柱是不可或缺的。
支柱 3:弹性
弹性是一个通用术语,它描述了满足严格停机时间 SLA 要求的高可用性或更普遍的“可靠性”。在应用程序不需要在线时,弹性可为较长的停机时间或时间段留出了余地,并且最终的一致性和服务交付是足够可用的。为此,我们提出了两种类型的弹性,每个现代应用都必须适当地满足弹性要求。
-
面向用户的弹性 —— 应用用户(无论是机器还是人)不应注意到因现代应用本身或其所依赖的任何服务或基础架构故障所引起的性能问题。当用户发现某个应用无法正常工作时,用户和应用团队之间的隐性合约就被破坏了。当今的人类用户希望其所访问和使用的任何服务或应用能够近乎 100% 地正常运行。机器可能更能接受内部自动化服务的中断,但任何类型的故障都会不可避免地引发级联反应,影响自动化服务和高度依赖的微服务。
-
故障转移弹性 —— 现代应用能够在 5 分钟内将任何关键服务恢复到足以满足处理平均工作负载的水平。这可能是一项艰巨的任务;当 Cloudflare 或亚马逊云科技等主要服务提供商的存储服务宕机时,整个互联网都可能会陷入停滞。也就是说,这里的重点是鼓励应用设计人员考虑作为应用设计的一个关键部分,故障转移到未受影响的计算资源(在系统故障时将工作转移到未受影响的计算资源上),这也是可自我修复的环境感知型现代应用的隐含要求。
支柱 4:敏捷性
敏捷性现在已褪去了流行语的光环。在现代应用的语境中,敏捷性很重要,因为它描述了一种以最少的工作来快速而明确地移动的理想状态。应用开发团队可以快速轻松地访问测试和推送新功能所需的资源,从而从敏捷性中受益。而借助敏捷性,DevOps 团队则可以简化、自动化代码和基础架构的检查和部署。
-
代码敏捷性 —— 能够根据应用开发团队的需要频繁地发布新代码。构建现代应用的高绩效公司必须创建流程和环境以支持他们每天多次发布新代码。应用本身的设计必须支持不断吸收新代码。在大多数情况下,这意味着应用由微服务组成并通过 API 链接,以加强松散耦合并减少应用内部代码的依赖性和刚性。
-
基础架构敏捷性 —— 能够启动或关闭基础架构以满足所有“客户”(包括应用开发团队、安全团队和 DevOps 团队)的需求的能力。这一点是前面提到的可扩展性和可移植性支柱的基础。为了实现和打造真正的敏捷开发和现代应用,企业必须为团队提供某种类型的基础架构自助服务以及现成的服务和应用目录。
六大原则
为了支持现代应用的四大支柱,大多数现代应用采用了(部分)遵循以下六大原则的架构:
-
不受平台限制 —— 这与可移植性有关但不完全相同。“不受平台限制”意味着应用为运行而构建,并不考虑运行平台或环境。容器已成为与平台无关运行时的事实标准,但应用不一定需要进行容器化才可以称为现代应用。
重要的是在应用开发开始时便遵循这一原则,以免日后再被迫针对平台进行代码抽象。
-
优先考虑开源软件 —— 开源软件 (OSS) 正在迅猛发展。现代应用要求团队能够深入了解代码,以进行可移植性和可扩展性设计,因此尽可能使用 OSS 对于打造现代应用至关重要。
-
一切即代码(尽可能) —— 现代应用必须以比人类操作更快的速度运行。现代应用要求和属性的各个方面的自动化和程序化定义现在都不能确定。当然,目前还没有可完全自动化的应用,因此人类必须参与制定关键决策和解决异常问题。但现代应用应通过稳定、持续地将更多定义和功能融于代码中并远离“部落知识 (tribal knowledge)”或运行手册来向这一方向迈进。
-
使用自动化 CI/CD 作为本地/默认状态进行设计 —— 在大多数情况下,应用构建完成之后便提交到 CI/CD 流水线。现代应用从头开始设计,考虑了 CI/CD 自动化的最终要求(现代应用从开始设计,就考虑了 CI/CD 自动化的最终要求),包括代码推送、基础架构部署,甚至安全要求。
-
实践安全开发 —— 尽管每个人都同意这很重要,但鲜有人真正做到这一点。这意味着在应用开发过程中尽早使用软件组合分析(SCA)、静态应用安全测试(SAST)、动态代码分析(DCA)及格式检查器测试所有代码,同时也意味着在部署之前测试所有代码。在实时部署之前,CI/CD 流水线必须需要一个“测试完成”标志。对于 DevOps 团队来说,这也意味着确保遵循安全最佳实践,例如加密内部微服务流量,在 WAF 启动和运行之后部署应用,以及自动更新和轮换数字证书。
-
广泛分布的存储和基础架构 —— 现代应用的最终用户无处不在。这意味着他们可能不仅在家中、公司或购物途中,也可能在世界的任何地方,甚至是在提供 WiFi 的飞机上!现代应用必须承认这一点,并进行全球分布式交付和存储功能设计。
此外,现代应用应利用分布式计算的优势来提高弹性、性能和可扩展性。真正的分布式(不仅仅是分片)存储能够确保数据的一致性和始终可用性,从而显著提高四大支柱的交付能力。真正的分布式基础架构(不仅仅是在单个地理位置)对于满足四大支柱的要求也至关重要。将存储和计算资源迁移到离客户(无论他们身在何处)更近的地方可提高存储和计算性能。跨多个区域、云或混合部署复制存储和计算资源可确保提供更高的弹性和可扩展性。
结论:现代应用定义既是一份清单又是一种思维
就像薛定谔的猫一样,现代应用的开发将同时存在两种状态,包括当前云环境和混合环境的真实世界,以及我们开发和交付应用所面临的时间和预算限制。完全自动化、高度安全、完全不受限、可即时扩展的完美的现代应用是一种理想的状态。而现实情况中,应用是杂乱无章的。您可能正在运行一个不在容器中的单体应用,它无法在五分钟内将容量翻倍,并且无法在不重构代码的情况下轻松迁移到其他环境。但这并不意味着本文列出的现代应用的支柱和原则无法帮助您或引导您进入更好的状态。
此外,我们预计,随着技术世界的变化和扩展,我们将不得不修改我们的定义。目前有一些软件模型并不完全符合定义:无服务器计算、日益复杂的低代码/无代码应用平台和人工智能驱动的安全应用、具有边缘节点计算能力的 CDN 等等。因此,这份定义将随着技术的扩展而演变。正如“十二要素应用宣言” 在今天仍然适用一样,我们希望现代应用的定义在未来也依然能够适用。在当前状态下,我们希望它可以指导您以最佳的方式为用户、开发人员及所有其他利益相关者构建应用。