Chinaunix首页 | 论坛 | 博客
  • 博客访问: 15577
  • 博文数量: 7
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 87
  • 用 户 组: 普通用户
  • 注册时间: 2017-05-12 16:45
文章分类

全部博文(7)

文章存档

2021年(1)

2017年(6)

我的朋友
最近访客

分类: 架构设计与优化

2021-10-14 20:14:55

简介

软件通常会作为一种服务来交付,即软件即服务(SaaS)。12-Factor原则为构建SaaS应用提供了以下的方法论:

  • 使用标准化流程自动配置,减少开发者的学习成本。
  • 和操作系统解偶,使其可以在各个系统间提供最大的移植性。
  • 适合部署在现代的云计算平台上,从而在服务器和系统管理方面节省资源。
  • 将开发环境与生产环境的差异降至最低,并使用持续交付实现敏捷开发。
  • 可以在工具、架构和开发流程不发生明显变化的前提下实现拓展。

该理论适应任何语言和后端服务(数据库、消息队列、缓存等)开发的应用程序。

基准代码(Codebase)

一份基准代码,多份部署。

应用代码使用版本控制系统来管理,常用的工具有GitSVN等。一份用跟踪代码所有修订的数据库称为代码库


一份基准代码

基准代码和应用之间总是保持一一对应的关系:

  • 一旦有多个基准代码,则不能称之为一个应用,而是一个分布式系统。分布式系统中的每个组件都是一个应用,每个应用都可以使用12-Factor,原则进行开发。
  • 多个应用共享一份记者代码有悖于12-Factor原则。解决方法是将共享的代码拆成独立的类库,通过依赖管理去使用它们。

多份部署

每个应用只对应一份基准代码,但可以同时存在多份部署,每份部署相当于运行一个应用的实例。

多份部署的区别在于:

  • 可以存在不同的配置文件对应不同的环境。例如:开发环境、测试环境、预发布环境、生产环境等。
  • 可以使用不同的版本。例如:开发环境的版本可能高于预发布环境,还没有同步到预发布环境的版本,同理,预发布环境版本可能高于生产环境版本。

依赖(Dependencies

显式声明依赖关系

大多数的编程语言都会提供一个包管理系统或工具,其中包含所有的依赖库,例如Golang的vendor目录存放了该应用的所有依赖包。

12-Factor原则下的应用会通过依赖清单来显式确切地声明所有的依赖项。在运行工程中通过依赖隔离工具来保证应用不会去调用系统中存在但依赖清单中未声明的依赖项。

显式声明依赖项的优点在于可以简化环境配置流程,开发者关注应用的基准代码,而依赖库则由依赖库管理工具来管理和配置。例如,Golang中的包管理工具dep等。

配置(Config)

在环境中存储配置

通常,应用的配置在不同的发布环境中(例如:开发、预发布、生产环境)会有很大的差异,其中包括:

  • 数据库、Redis等后端服务的配置
  • 每份部署特有的配置,例如域名
  • 第三方服务的证书等

12-Factor原则要求代码和配置严格分离,而不应该通过代码常量的形式写在代理里面。配置在不同的部署环境中存在大幅差异,但是代码却是完全一致的。

判断一个应用是否正确地将配置排除在代码外,可以看应用的基准代码是否可以立即开源而不担心暴露敏感信息。

12-Factor原则建议将应用的配置存储在环境变量中,环境变量可以方便在不同的部署环境中修改,而不侵入原有的代码。(例如,k8s的大部分代码配置是通过环境变量的方式来传入的)。

12-Factor应用中,环境变量的粒度要足够小且相对独立。当应用需要拓展时,可以平滑过渡。

后端服务(Backing Services

把后端服务当作附加资源

后端服务指程序运行时所需要通过网络调用的各种服务,例如:数据库(MySQL),消息/队列系统(),SMTP 邮件发送服务(),以及缓存系统()。

其中可以根据管理对象分为本地服务(例如本地数据库)和第三方服务(例如Amason S3)。对于12-Factor应用来说都是附加资源,没有区别对待,当其中一份后端服务失效后,可以通过切换到原先备份的后端服务中,而不需要修改代码(但可能需要修改配置)。12-Factor应用与后端服务保持松耦合的关系。

构建、发布、运行(Build、Release、Run)

严格分离构建和运行

基准代码转化成一份部署需要经过三个阶段:

  • 构建阶段:指代码转化为可执行包的过程。构建过程会使用指定版本的代码,获取依赖项,编译生成二进制文件和资源文件。
  • 发布阶段:将构建的结果与当前部署所需的配置结合,并可以在运行环境中使用。
  • 运行阶段(运行时):指针对指定的发布版本在执行环境中启动一系列应用程序的进程。

12-Factor应用严格区分构建、发布、运行三个步骤,每一个发布版本对应一个唯一的发布ID,可以使用时间戳或递增的版本序列号。

如果需要修改则需要产生一个新的发布版本,如果需要回退,则回退到之前指定的发布版本。

新代码部署之前,由开发人员触发构建操作,构建阶段可以相对复杂一些,方便错误信息可以展示出来得到妥善处理。运行阶段可以人为触发或自动运行,运行阶段应该保持尽可能少的模块。

进程(Processes)

以一个或者多个无状态进程运行应用

12要素应用的进程必须是无状态且无共享的,任何需要持久化的数据存储在后端服务中,例如:数据库。

内存区域和磁盘空间可以作为进程的缓存,12要素应用不需要关注这些缓存的持久化,而是运行其丢失,例如重启的时候。

进程的二进制文件应该在构建阶段只想编译而不是运行阶段。

当应用使用到粘性Session,即将用户的session数据缓存到进场的内存中,将同一用户的后续请求路由到同一个进程。12要素应用反对这种处理方式,而是建议将session的数据保存在redis/memcached带有过期时间的缓存中。

端口绑定(Port Binding)

通过端口棒的提供服务

应用通过端口棒的提供服务,并监听发送至该端口的请求。端口绑定的方式意味着一个应用也可以成为另一个应用的后端服务,例如提供某些API请求。

并发(Concurrency)

通过进程模型进行扩展

12-Factor应用中,开发人员可以将不同的工作分配给不同类型进程,例如HTTP请求由web进程来处理,常驻的后代工作由worker进程来处理(k8s的设计中就是经常用不同类型的manager来处理不同的任何)。

12-Factor应用的进程具有无共享、水平分区的特性,使得水平扩展较为容易。

12-Factor应用的进程不需要守护进程或者是写入PID文件,而是通过进程管理器(例如systemd)来管理输出流、响应崩溃的进程,以及处理用户触发的重启或者关闭超级进程的操作。

易处理(Disposability)

快速启动和优雅退出,可最大化的健壮性

12-Factor应用的进程是易处理的,意思是说它们可以快速的启动和停止,这样有利于快速部署和弹性伸缩实例。

进程应用追求最小的启动时间,这样可以敏捷发布,增强健壮性,当出现问题可以快速在别的机器不是一个实例。

进程一旦接收到终止信号(SIGTERM)就会优雅退出。就网络进程而言,优雅退出指停止监听服务的端口,拒绝所有新的请求,并继续执行当前已接收的请求,然后退出。此类型的进程所隐含的要求是HTTP请求大多都很短,而且长时间轮询中,客户端在丢失连接后应该立马尝试重连。对于worker进程来说,优雅退出是指将当前任务退回队列。例如:RabbitMQ中,worker可以发送一个NACK信号。任务终止并退回队列会在worker断开时自动触发。有锁机制的系统诸如Delayed Job则需要确定释放了系统资源。此类型的进程所隐含的要求是,任务都应该可以重复执行,这主要由将结果包装进程事务或者使用重复操作确保幂等来实现。

进程还应该在面对突然挂掉时保持健壮,例如底层硬件故障。虽然这种情况比起优雅退出来说少之又少,但终究有可能发生。一种推荐的方式是使用一个健壮的后端队列,它可以在客户端断开或者超时时自动退回任务。无论如何,12-Factor应用都应该可以设计能够应对意外的、不优雅退出。Crash-onlydesign将这种概念转化为合乎逻辑的理论

开发环境与线上环境等价(Dev/Prod parity)

尽可能的保持开发、测试、预发布、线上环境相同

不通的发布环境可能存在以下差异:

  • 时间差异:开发到部署的周期较长。
  • 人员差异:开发人员只负责开发,运维人员只负责部署。分工过于隔离。
  • 工具差异:不同环境的配置和运行环境,是呀的后端类型可能存在不同。

经历缩小本地与现实的差异,缩短上线周期,开发运维一体化,保证开发环境和线上运行环境的一致(例如:通过容器化部署方式)。

日志(Logs)

把日志当作事件流

日志应该是事件流的汇总。12-Factor应用本身不考虑存储自己的日志输出流,不去写或者管理日志文件,而是通过标准输出(stdout)的方式。

日志的标准输出可以通过其他组件截获,整合其他的日子输出流,一并发给统一的日志中心处理,用于查看或存档。例如:日志收集开源工具Fluentd。

截获的日志流可以输出至文件,或者在终端实时查看。最重要的是可以发送到Splunk这样的日志索引以及分析系统,提供后续的分析统计及健康告警等功能。例如:

  • 找出过去一段时间的特殊事件。
  • 图形化一个大规模的趋势,入每分钟的请求量。
  • 根据用户定义的条件触发告警,入每分钟报错数超过某个告警线。

但我们现实使用时,并没有按照上述标准来落实,同时市面主流也没有遵循。而是将日志流写输出到具体文件,使用具体的日志采集器采集上报到日志服务器如:智研-日志汇。

管理进程(Adminstrative Process)

后台管理任务当作一次性进程运行

将管理任务当作一次性任务来运行。一次性管理进程应该和正常的常驻进程使用相同的运行环境。这些管理进程和任何其他的进程一样使用相同的代码和配置,基于某个发布版本运行。后台管理代码应该随其他应用程序代码一起发布,从而避免同步问题。


参考文章:

阅读(563) | 评论(0) | 转发(0) |
0

上一篇:redis 操作命令简单的总结

下一篇:没有了

给主人留下些什么吧!~~