12要素应用程序是用于构建可扩展和高性能,独立且最具弹性的应用程序的方法论或一组原则。
如今,软件通常会作为一种服务来交付,它们被称为网络应用程序,或软件即服务(SaaS)。12-Factor 为构建如下的 SaaS 应用提供了方法论:
- 使用标准化流程自动配置,从而使新的开发者花费最少的学习成本加入这个项目。
- 和操作系统之间尽可能的划清界限,在各个系统中提供最大的可移植性。
- 适合部署在现代的云计算平台,从而在服务器和系统管理方面节省资源。
- 将开发环境和生产环境的差异降至最低,并使用持续交付实施敏捷开发。
- 可以在工具、架构和开发流程不发生明显变化的前提下实现扩展。
12要素应用程序原则适用于任意语言和后端服务(数据库、消息队列、缓存等)开发的应用程序。
12要素应用程序原则非常流行,因为它与微服务原则保持一致。
十二要素应用程序原则
- 代码库(一份基准代码,多份部署)
- 依赖关系(显式声明并隔离依赖关系)
- 配置(在环境中存储配置)
- 后端服务(把后端服务当作附加资源)
- 构建,发布和运行(完全独立的构建和运行阶段)
- 进程(通过一个或多个无状态进程运行应用程序)
- 端口绑定(通过端口绑定提供服务)
- 并发(通过进程模型扩展)
- 易处理(通过快速启动和优雅停止来最大程度地提高健壮性)
- 环境等价(尽可能保持开发,预发布和生产环境的相似)
- 日志(将日志处理作为事件流)
- 管理进程(后台管理任务当作一次性进程运行)
1. 代码库(一份基准代码,多份部署)
12要素应用程序主张每个应用程序都应具有自己的代码库(存储库)。避免多个版本的多个代码库。请注意,有分支可以。即对于所有部署环境,应该只有一个存储库,而不应该有多个。
从12个因素角度看待应用程序,部署意味着该应用程序的实例运行。此外,每个开发人员都有在其本地开发环境中运行的该应用程序的一个副本,每个副本也都具有以下条件:部署。
在多个部署中可能会激活不同的版本。
- 微服务:在微服务中,每个服务应具有自己的代码库。拥有独立的代码库可帮助你简化应用程序的CI/CD流程。
12要素应用程序主张不要在应用程序之间共享代码。如果需要共享,则需要构建一个库并将其作为依赖项,并通过像maven这样的软件包进行管理。
2. 依赖关系(显式声明并隔离依赖关系)
它讨论了使用依赖项管理工具从外部管理依赖项,而不是将其添加到代码库中。
从Java的角度来看,你可以将Gradle视为依赖管理器。你将在build.gradle文件中提及所有依赖项,你的应用程序将从maven存储库或其他各种存储库中下载所有提及的依赖项。
你还需要从操作系统/执行环境的角度考虑依赖关系。
微服务:所有应用程序软件包都将通过软件包管理器(如sbt,maven)进行管理。
- 在非容器化环境中,你可以使用chef,ansible等配置管理工具来安装系统级依赖项。
- 对于容器化环境,你可以使用dockerfile。
3. 配置(在环境中存储配置)
环境部署之间的任何变化都被视为配置。这包括:
- 数据库连接和凭据,系统集成端点
- 外部服务(例如Amazon S3或Twitter或任何其他外部应用程序)的凭据
- 特定于应用程序的信息,例如IP地址,端口和主机名等。
你不应在代码库中将任何配置值硬编码为常量。这直接违反了12要素应用程序原则。
12要素应用程序原则建议将配置值保存在环境变量中。
它提倡严格区分代码和配置。无论将应用程序部署在何处,代码都必须相同。
- 微服务: 从应用程序外部化配置。在微服务服务环境中,你可以从配置中心(如spring-cloud-config)管理应用程序的配置。
4. 后端服务(把后端服务当作附加资源)
根据12要素应用程序原则, 应用不区别对待本地或第三方服务。 对应用程序而言,两种都是附加资源,通过一个 url 或是其他存储在配置中的服务定位 / 服务证书来获取数据。
12要素应用程序的任意部署 ,都应该可以在不进行任何代码改动的情况下,将本地 MySQL 数据库换成第三方服务 (例如 Amazon RDS)。类似的,本地 SMTP 服务应该也可以和第三方 SMTP 服务 (例如 Postmark) 互换。
为此,你不应对应用程序进行任何代码更改。只有配置更改才能解决此问题。
- 微服务: 在微服务生态系统中,服务外部的任何内容都被视为附加资源。可以在任何给定时间点交换资源,而不会影响服务。
通过遵循基于接口的编程,可以动态变更组件而不会影响系统。基于插件的实施还可以帮助你支持多个提供程序。
5. 构建,发布和运行(完全独立的构建和运行阶段)
应用程序必须在构建,发布和运行阶段之间严格分开。让我们更详细地了解每个阶段。
- 构建阶段: 将代码转换为可执行的软件包。
- 发布阶段:从构建阶段获取软件包,并与部署环境的配置结合起来,使你的应用程序可以运行。
- 运行阶段:运行你的应用程序。
微服务: 你可以使用CI/CD工具来自动化构建和部署过程。Docker镜像使你可以更轻松地更有效地分离构建,发布和运行阶段。
6. 进程(通过一个或多个无状态进程运行应用程序)
一个应用程序可以具有一个或多个实例/进程,以满足用户/客户的需求。
根据12要素原则,应用程序不应将数据存储在内存中,而必须将其保存到存储中并从那里使用。就状态而言,你的应用程序应将状态存储在数据库中,而不是存储在进程的内存中。
避免使用粘性会话,使用粘性会话违反了12要素应用程序原则。如果要存储会话信息,则可以根据需要选择Redis或memcached或任何其他缓存提供程序。
通过遵循这些步骤,你的应用程序可以高度扩展,而不会对系统造成任何影响
- 微服务: 通过采用REST的无状态性质,你可以根据需要对服务进行水平扩展,而没有任何影响。如果你的系统仍然需要维护状态,请使用Redis,Memcached等来存储状态,而不是在内存中。
7. 端口绑定(通过端口绑定提供服务)
十二要素应用程序是完全独立的, 不依赖于任何网络服务器就可以创建一个面向网络的服务 。
简而言之,这就是使你的应用程序独立运行,而不是将其部署到任何外部Web服务器中。
- 微服务: Spring Boot就是这一示例。默认情况下,Spring Boot带有嵌入式的tomcat,jetty或undertow容器。
8. 并发(通过进程模型扩展)
这里讨论扩展应用程序。十二要素应用程序原则建议考虑将应用程序作为多个进程/实例运行,而不是在一个大型系统中运行。你仍然可以选择加入线程以改善对请求的并发处理。
简而言之,十二要素应用程序原则主张采用水平缩放而不是垂直缩放。
垂直缩放-向系统添加其他硬件,水平缩放-添加应用程序的其他实例。
- 微服务: 通过采用容器化,可以根据需求水平扩展应用程序。
9. 易处理(通过快速启动和优雅停止来最大程度地提高健壮性)
十二要素应用程序的过程是一次性的,这意味着它们可以立即启动或停止。当应用程序关闭或启动时,实例不应影响应用程序状态。
正常关机非常重要。系统必须确保状态正确。
添加新实例或根据需要删除现有实例时,系统不应受到影响。
由于各种原因,系统确实崩溃。系统应确保影响最小,并且应用程序应以有效状态存储。
- 微服务: 通过在微服务的部署过程中采用容器化,你的应用程序在最大程度上隐式遵循了这一原则。Docker容器可以立即启动或停止。将请求,状态或会话数据存储在队列或其他支持服务中可确保在容器崩溃的情况下无缝处理请求。
10. 环境等价(尽可能保持开发,预发布和生产环境的相似)
十二因素方法论建议将开发和生产环境之间的差距保持在最小。这样可以减少在特定环境中暴露错误的风险。
- 微服务: 这是使用容器化技术运行微服务的固有功能。
11. 日志(将日志处理作为事件流)
日志对于解决生产问题或了解用户行为至关重要。日志可以查看正在运行的应用程序的行为。
十二要素应用主张将日志生成与处理日志信息分开。 应用本身从不考虑存储自己的输出流,不试图去写或者管理日志文件。相反,应用每一个运行的进程都会直接的标准输出 (stdout) 事件流。 然后,由其他中间件负责捕获,存储,管理日志。
- 微服务: 在微服务中,可观察性是头等公民。可通过使用APM工具(ELK,Newrelic和其他工具)或日志聚合工具(例如Splunk,日志等)来实现可观察性。
通过遵循上述准则,当软件故障时,你所需要做的就是调试问题,即转到工具的仪表板并进行搜索。
12. 管理进程(后台管理任务作为一次性进程运行)
作为应用程序部署的一部分,有许多一次性过程,例如数据迁移,在特定环境中执行一次性脚本。
十二要素原则主张将此类任务作为应用程序代码库的一部分保留在存储库中。
确保一次性脚本是自动化的,这样你就不必担心在发布构建版本之前手动执行它们。
十二因素原则还建议使用内置工具在生产服务器上运行那些脚本。
- 微服务: 容器化可以帮助你将一次性流程作为一项任务运行。
参考文献:
https://12factor.net/build-release-run https://www.nginx.com/blog/microservices-reference-architecture-nginx-twelve-factor-app/ https://blog.scottlogic.com/2017 /07/17/successful-microservices-with-12factor-app.html
译文链接:https://dzone.com/articles/12-factor-app-principles-and-cloud-native-microser
登录后评论
立即登录 注册