本文翻译自 How To Understand Twelve-Factor Methodology In Spring Boot Applications (opens new window),作者 OLEKSII (opens new window)
十二要素应用程序是构建现代可扩展应用程序架构所需的一系列原则。本篇文章将从 Spring Boot
应用的角度回顾这些原则。
# 一、代码库
应用程序在版本控制系统(如 Git
)中进行跟踪。
代码库和应用程序之间是一对一的关系。因此,每个 Spring Boot
应用程序都有自己的代码库。这些应用程序构成了一个分布式系统。多个部署(如测试、阶段、生产等)的代码是相同的。
# 二、依赖关系
在十二要素应用程序中,系统依赖关系是明确声明的。
在 Spring Boot 中,可以使用 Maven
或 Gradle
来实现这些目的。这些工具可用于指定所需的应用程序依赖关系。此外,跨依赖关系可能存在的问题也得到了解决。
# 三、配置
如前所述,每个应用程序只有一个代码库。但是,相同的代码会用于多个部署。因此,这些部署需要一些配置功能。
在 Spring Boot
中,属性可以用来解决这个问题。属性可以通过多种方式指定。例如,可以在 application.yml
文件中指定默认值。在环境变量的帮助下,每个部署都可以覆盖所需的属性。更多详情可参阅 Spring Boot
的文档。
# 四、 备份服务
每个应用程序都可以使用多个外部或第三方服务。
可以是数据库(如 MySQL
)、消息代理(如 Kafka
)、第三方 API 等。每个服务都应像资源一样运行。这意味着,你的代码应同时在 Docker
中的 MySQL
和 AWS
中的 MySQL
上运行,而无需做任何更改。
在 Spring Boot
中,可以通过 Spring Boot
属性、特殊接口和类(如 Spring Data Repository
)来实现。
# 五、构建、发布、运行
十二要素方法需要三个不同的阶段,才能将源代码转化为运行中的应用程序。
# 构建
首先,将源代码转化为可执行文件。可以使用 Maven
或 Gradle
来构建目标 jar 文件。
# 发布
第二步,将可执行文件与特定配置相结合。例如,可以创建一个 Docker
镜像,将 jar 文件与所需配置相结合。
# 运行
在这一步中,可以创建一个 Docker
容器,根据上一步的映像运行应用程序。这意味着,在必要时,我们可以在不同版本的应用程序之间快速切换。如果当前版本有一些错误,可以使用之前的 Docker
镜像来运行应用程序。
# 六、程序
十二要素应用程序是无状态的,不共享任何数据。不过,数据可以保存在数据库等有状态备份服务中。
让我们来看一个例子。想象一下,我们有一个带有 MySQL
数据库的应用程序。对数据库的某些请求速度很慢。因此,我们使用了内存中的 Caffeine
缓存。数据更新时,缓存会失效。只有一个节点部署时,一切正常。
一段时间后,系统负载不断增加。我们希望通过添加第二个节点来扩展我们的应用程序。缓存位于每个节点上。因此,用户在两次后续请求中看到的结果是不同的。用户更新了记录。第一个节点会使其内存缓存失效。一方面,用户可以看到新数据。用户再次读取数据。第二个节点(拥有旧缓存)会以旧数据做出响应。
为了克服这个问题,应用程序是无状态的。这种缓存可以位于分布式缓存中,如 Redis
。
# 七、端口绑定
在以前使用的典型 Java 应用程序中,可执行文件以 war 文件的形式出现。该文件在 Tomcat
等容器中执行。
在十二要素应用程序中,可执行文件是独立的。Spring Boot
应用程序内部依赖于 Tomcat
。因此,jar 是自包含的,运行应用程序只需要一个 java 环境。唯一需要指定的是应用程序应使用的目标端口。这可以通过配置属性完成。
# 八、并发性
十二要素应用程序是为扩展而设计的。Java 应用程序作为与 JVM 绑定的单个进程运行。为了扩展 Spring Boot 应用程序,必须启动一个新实例。在 五、构建、发布、运行一节中,Docker
容器被描述为运行 Spring Boot 应用程序的一种方式。因此,为了扩展,可以使用 Kubernetes
。
# 九、可处置性
十二要素应用程序应具有快速启动和优雅关闭的特点。
这意味着,同一应用程序的实例可以随时启动或停止。这不应影响应用程序。为了实现这一点,当应用程序实例停止时,该实例应停止监听传入请求,完成对所有当前请求的处理,并优雅地停止。
在 Spring Boot
中,这可以通过应用程序事件来实现。
# 十、开发/生产比价
在典型的应用程序开发流程中,开发与生产之间存在很大差距。应用程序是在本地环境中开发的,开发人员不参与部署过程,开发人员可以使用与生产不同的工具。
十二要素应用程序是为持续部署而设计的,目的就是尽量缩小这种差距。Spring Boot
和 Docker
使之成为可能。开发人员可以使用与生产环境中相同的工具快速编写应用程序。
# 十一、日志日志
日志是软件应用程序的重要组成部分,可提供运行应用程序的可见性。
在十二要素应用程序中,日志被写入标准输出。执行环境应负责处理日志。Fluentd
可用于收集此类日志,并将其淡入日志索引工具。Elasticseach
和 Kibana
就是这方面的常见例子。
# 十二、管理流程
经常需要在应用程序上运行一次性任务或例行程序。十二要素应用方法论建议将这些任务纳入应用程序代码中。
例如,典型的任务是数据库迁移。可通过 Flyway
或 Liquibase
实现。