十二因子原则和云原生微服务 - DZone


一个由12个要素因子组成的应用程序是一种用于构建可扩展和高性能,独立且最具弹性的企业应用程序的方法论或一组原则。它建立了用于创建健壮的企业应用程序的一般原则和准则。12要素应用程序原则非常流行,因为它与微服务原则保持一致。
以下是12要素原则

  • 代码库(修订控制中跟踪一个代码库,许多部署)
  • 依赖关系(明确声明并隔离依赖关系)
  • Config(在环境中存储配置)
  • 支持服务(将处理支持资源作为附加资源)
  • 构建,发布和运行(完全独立的构建和运行阶段)
  • 进程(将应用程序作为一个或多个无状态进程执行)
  • 端口绑定(通过端口绑定导出服务)
  • 并发(通过流程模型扩展)
  • 一次性性(通过快速启动和正常关闭来最大程度地提高鲁棒性)
  • 开发/产品奇偶校验(保持开发,暂存和生产尽可能相似)
  • 日志(将处理日志作为事件流)
  • 管理流程(将管理/管理任务作为一次性流程运行)

 
代码库(版本控制中跟踪一个代码库,许多部署)
12要素应用程序主张每个应用程序都应具有自己的代码库(repos)。必须避免多个版本的多个代码库。请注意,有分支机构可以。即对于所有部署环境,应该只有一个存储库,而不应该有多个。
共享相同代码的多个应用违反了十二个因素。在这里,您应该选择加入共享库。
从具有12个因素的应用程序角度看待应用程序,部署意味着该应用程序的运行实例,例如生产,登台,质量检查等。此外,每个开发人员都有一个在其本地开发环境中运行的应用程序的副本,每个副本也都具有以下条件:部署。
在多个部署中可能会激活不同的版本(该版本就像是在一个环境中可用但在其他环境中不可用的代码更改)。
微服务: 在微服务中,每个服务都应具有自己的代码库。拥有独立的代码库可帮助您简化应用程序的CI / CD流程。
十二因子应用程序主张不要在应用程序之间共享代码。如果需要共享,则需要构建一个库并使它成为依赖项,并通过像maven这样的软件包存储库进行管理。
 
依赖关系(明确声明和隔离依赖关系)
讨论使用依赖项管理工具从外部管理依赖项,而不是将其添加到您的代码库中。
从Java的角度来看,您可以将Gradle视为依赖管理器。您将在build.gradle文件中提及所有依赖项,并且您的应用程序将从maven存储库或其他各种存储库中下载所有提及的依赖项。
您还需要从操作系统/执行环境的角度考虑依赖性。
微服务:所有应用程序包将通过sbt,maven等包管理器进行管理。
  • 在非容器化环境中,您可以使用chef,ansible等配置管理工具来安装系统级依赖项。
  • 对于容器化环境,可以使用Dockerfile。

 
Config(在环境中存储配置)
部署环境之间的任何变化都被视为配置。这包括:
  • 数据库连接和凭据,系统集成端点
  • 外部服务(例如Amazon S3或Twitter或任何其他外部应用程序)的凭据
  • 特定于应用程序的信息,例如IP地址,端口和主机名等。

您不应在代码库中将任何配置值硬编码为常量。这直接违反了12要素应用原则。
12要素应用程序原则建议将配置值保存在环境变量中。
它提倡严格区分代码和配置。无论将应用程序部署在何处,代码都必须相同。
根据“配置”,因环境而异的环境必须移至配置并通过环境变量进行管理。
微服务: 从应用程序外部化配置。在微服务服务环境中,您可以从源控件(如git(spring-cloud-config))管理应用程序的配置,并使用环境变量不维护源控件中的敏感信息。

支持服务(将处理后的资源作为附加资源)
根据12要素应用程序原则,后备服务是应用程序通过网络消费的应用程序/服务,是其正常运行的一部分。
数据库,Message Broker,应用程序通信的任何其他外部系统都被视为支持服务。
12因子应用程序可以自动将应用程序从一个提供程序交换到另一个提供程序,而无需对代码库进行任何进一步的修改。让我们说,您想将数据库服务器从MySQL更改为Aurora。为此,您不应对应用程序进行任何代码更改。只有配置更改才能解决此问题。
微服务: 在微服务生态系统中,服务外部的任何内容都被视为附加资源。可以在任何给定的时间点交换资源,而不会影响服务。
通过遵循基于接口的编程,可以动态交换提供程序而不会影响系统。基于插件的实施还可以帮助您支持多个提供程序。
 
构建,发布和运行(完全分开的构建和运行阶段)
应用程序必须在构建,发布和运行阶段之间严格分开。让我们更详细地了解每个阶段。
构建阶段: 将代码转换为可执行的包/构建包。
发布阶段:从构建阶段获取构建软件包,并与部署环境的配置结合起来,使您的应用程序可以运行。
运行阶段:就像在执行环境中运行您的应用程序一样。
微服务:
您可以使用CI / CD工具来自动化构建和部署过程。Docker映像使您可以更轻松地更有效地分离构建,发布和运行阶段。
 
进程(将应用作为一个或多个无状态进程执行)
该应用程序在执行环境中作为一个进程执行。一个应用程序可以具有一个或多个实例/进程,以满足用户/客户的需求。
根据12因子原则,应用程序不应将数据存储在内存中,而必须将其保存到存储中并从那里使用。就状态而言,您的应用程序应将状态存储在数据库中,而不是存储在进程的内存中。
避免使用粘性会话(httpsession中存储用户数据),使用粘性会话违反了12要素应用程序原则。如果要存储会话信息,则可以根据需要选择Redis或Memcached或任何其他缓存提供程序。
通过遵循这些步骤,您的应用程序可以高度扩展,而不会对系统造成任何影响
微服务: 通过采用REST的无状态性质,您的服务可以根据需求进行水平扩展,而零影响。如果您的系统仍然需要维护状态,请使用附加的资源(Redis,Memcached或数据存储)来存储状态,而不是在内存中。
 
端口绑定(通过端口绑定导出服务)
具有十二个要素的应用程序是完全独立的,并且不依赖于将网络服务器的运行时注入到执行环境中来创建面向Web的服务。Web应用程序通过绑定到端口并侦听来自该端口的请求,将HTTP作为服务导出。
简而言之,这就是将您的应用程序作为独立的应用程序,而不是将其部署到任何外部Web服务器中。
微服务:  Spring启动就是这一示例。默认情况下,Spring Boot带有嵌入式的tomcat,jetty或undertow。
 
并发(通过流程模型进行横向扩展)
这里讨论如何扩展应用程序:十二要素应用程序原则建议考虑将应用程序作为多个进程/实例运行,而不是在一个大型系统中运行。您仍然可以选择加入线程以改善对请求的并发处理。
简而言之,十二要素应用程序原则主张选择采用水平缩放而不是垂直缩放。
(垂直缩放-向系统添加其他硬件
水平缩放-添加应用程序的其他实例)
微服务: 通过采用容器化,可以根据需求水平扩展应用程序。
 
一次性(通过快速启动和平稳关机最大程度地提高稳定性)
十二要素应用程序的流程是一次性的,这意味着它们可以立即启动或停止。当应用程序关闭或启动时,实例不应影响应用程序状态。
正常关机非常重要。系统必须确保状态正确。
添加新实例或根据需要删除现有实例时,系统不应受到影响。这也称为系统可处置性。
由于各种原因,系统确实崩溃。系统应确保影响最小,并且应用程序应以有效状态存储。
微服务: 通过在微服务的部署过程中采用容器化,您的应用程序将在最大程度上隐式遵循该原则。Docker容器可以立即启动或停止。将请求,状态或会话数据存储在队列或其他支持服务中可确保在容器崩溃的情况下无缝处理请求。
 
开发/产品奇偶校验(尽可能保持开发,登台和生产)
十二要素方法论建议将开发和生产环境之间的差距保持在最小。这样可以减少在特定环境中显示错误的风险。
微服务: 这是使用容器化技术运行的微服务的固有功能。
 
日志(作为事件流的处理日志)
日志对于解决生产问题或了解用户行为至关重要。日志可以查看正在运行的应用程序的行为。
十二要素应用原则主张将日志生成与处理日志信息分开。在应用程序中,日志将被写为标准输出,执行环境负责捕获,存储,管理,此类流的归档应由执行环境处理。
微服务: 在微服务中,可观察性是头等公民。可以通过使用APM工具(ELK,Newrelic和其他工具)或日志聚合工具(例如Splunk,日志等)来实现可观察性。
通过遵循上述准则,您所需要做的就是调试问题,即转到工具的中央仪表板并进行搜索。
 
管理员流程(作为一次性流程运行管理员/管理任务)
作为应用程序部署的一部分,有几个一次性流程,例如数据迁移,在特定环境中执行一次性脚本。
十二要素原则提倡将此类管理任务作为应用程序代码库的一部分保留在存储库中。这样,一次性脚本将遵循为您的代码库定义的相同流程。
确保一次性脚本是自动化的,这样您就不必担心在发布构建版本之前手动执行它们。
十二因素原则还建议使用执行环境的内置工具在生产服务器上运行那些脚本。
微服务: 容器化还可以帮助您将一次性流程作为一项任务运行,并在执行过程中自动将其关闭。