十二要素应用程序是一组用于构建 Web 应用程序的 12 条原则或最佳实践,如今这些应用程序通常被称为软件即服务 (SAAS) 应用程序。它由 Heroku 的联合创始人 Adam Wiggins 先生于 2011 年发布。 这些原则是在 Heroku(一个平台即服务)的工作人员获得的所有经验和观察的结果。曾在其上部署过大量各种软件即服务应用程序。
这些原则帮助我们创建使用声明式编程实现设置自动化的应用程序,这反过来又减少了新开发人员加入时项目的开发时间和成本,不依赖任何特定的操作系统,易于移植,高度适合在云上部署,允许持续部署,并且易于水平扩展,无需对代码库进行大量更改。因素如下:
1. 代码库
在版本控制中跟踪多个部署的每个应用程序的单个代码库。让我们打破它的官方声明,并尝试理解其中的两个主要术语。简单地说,代码库是不包括工具生成的类或目标文件的所有人工编写的源代码。部署是指该特定应用程序的单个运行实例。每个应用程序必须只有一个代码库。每个这样的代码库都必须在版本控制系统中进行管理。一些流行的 VCS(版本控制系统)包括 git、svn 和 mercurial。如果存在多个代码库,那么它就不是一个应用程序,而是一个分布式系统。该系统的每个组件都将被称为一个应用程序,该应用程序应遵循 12 要素应用程序的原则。
2. 依赖
显式声明和隔离依赖项。我们都必须在我们的编程生涯中至少观察到一次,我们出于某种目的下载了一个Python库,然后发现我们下载了错误版本的库或在我们的系统中安装了错误版本的Python 。这通常是因为管理依赖项的任务交给了开发人员。因此,这个因素表明我们必须始终在清单文件中声明依赖项,该文件包含依赖项的元数据,如名称、版本。它提高了开发速度,因为现在开发人员无需管理库的正确版本。不再需要显式下载所需的 JAR。
3. 配置
将配置存储在环境中。源代码和配置必须完全分开。我们必须在环境变量中存储所有配置,如 DB 凭证、路径、URI,就像行业中的一般做法一样,应用程序的配置因环境而异,如 dev、test、prod 等。此外,不应将配置存储在 git 中在纯文本中。有一种非常简单的方法,您可以通过问自己是否可以在不进行任何更改且不损害任何凭据的情况下立即将应用程序开源来检查您当前的应用程序是否遵循此Config原则。
4. 支持服务
将后备服务视为附加资源。如果我们用非常简单的术语说话,那么您的应用程序通过网络使用的任何服务都称为支持服务。您的应用程序必须将这些服务视为它通过网络消耗的资源。它为我们提供了优势,即我们的服务可以轻松互换并为我们的应用程序提供极大的可移植性。
一个简单的示例假设您的应用程序当前使用本地 PostgreSQL 数据库进行操作,然后只需更改 URL 和数据库凭据即可将其替换为您公司服务器上托管的数据库。
5. 构建、发布和运行
严格分离构建和运行阶段。应用程序的部署必须正确地分为三个不重叠的非依赖阶段,即构建、发布和运行。构建阶段构成代码的编译,最终生成 JAr 或 WAR 文件等工件。第二阶段,发布,采用上一阶段结束时生成的工件文件,并将特定环境的配置添加到其中。最后一个阶段包括应用程序实例的运行。
6. 流程
将应用程序作为一个或多个无状态进程执行。如果一个应用程序的实例可以随时创建和销毁,而不会对我们应用程序的整体功能产生任何影响,那么我们就说该应用程序遵循了这一原则。为了实现并实现这一原则,我们的应用程序必须将其生成的任何类型的数据存储在任何持久(有状态)数据存储中。但这并不意味着我们不能使用应用程序进程的内存。我们可以用它来存储作为临时存储。简单来说,必须避免使用粘性会话。粘性会话,简单来说,是指在进程的本地内存中捕获登录用户的会话数据,然后将来自该特定用户的每个后续请求定向到同一进程。粘性会话的问题在于它会导致应用程序实例之间的负载平衡不均衡。
7. 端口绑定
通过端口绑定导出服务。任何遵循此原则的应用程序都是完全独立的。它将 HTTP 作为服务导出,不需要像 tomcat 这样的任何服务器来监听请求。它将自己绑定到某个特定的端口,并侦听该端口上的所有请求。您还必须在设计在特定端口上运行的应用程序或微服务时观察到它,并且您使用邮递员在该特定端口上发出请求以获得响应。我们的服务将侦听哪个端口的信息也存储在配置文件本身中。
8.并发
通过流程模型向外扩展。遵循此原则的应用程序必须划分为更小的不同进程,而不是单个大型应用程序。每个这样的过程必须能够在任何时候独立地启动、终止和复制自身。这个原则允许非常容易地扩展我们的应用程序。通过横向扩展,我们指的是运行多个流程实例的水平扩展。由于存在独立的水平可扩展进程,它以一种非常简单的方式为我们的应用程序增加了并发性。
9. 一次性
通过快速启动和正常关闭最大限度地提高稳健性。应用程序的健壮性是指在不影响整个应用程序功能的情况下正常启动和终止其进程。例如,我们的应用程序的一个流程是将新添加到公司的员工的详细信息存储到数据库中。但是在这样做的同时,会发生意外错误,导致进程意外终止。但是,我们的应用程序或数据库的状态不得受其影响,并且该过程必须具有故障安全性。此外,它必须在需要时快速启动。
10. 开发/生产平价
使开发、登台和生产尽可能相似。它只是意味着开发和生产环境必须尽可能相似。所使用的流程、技术和基础设施必须相同。这将以某种方式帮助您:随着时间的推移可能发生的任何错误都将发生在开发阶段本身,而不是在生产中意外发生。这有助于持续部署我们的应用程序并减少开发时间和工作量。
11. 日志
将日志视为事件流。日志对于了解应用程序的内部工作非常重要,它可以是不同级别的,通常存储在存储中名为“logFile”的文件中。理想情况下,我们的十二要素应用程序不必担心日志的存储。每当请求进入系统时,都会生成相应的日志,并将它们视为一系列事件,可用于在出现问题时进行调试。
12. 管理流程
将管理/管理任务作为一次性流程运行。大多数应用程序需要在应用程序的实际流程开始之前执行一些一次性任务。这些任务不是经常需要的,因此,我们通常为它创建一个脚本,我们从其他环境运行。另一方面,十二因素方法说,这些脚本必须成为我们在版本控制系统中管理的代码库本身的一部分。这些任务还应遵循十二要素原则。