阅读笔记(十八)SAAS的奠基石12 factor-app《The Twelve-Factor App》

一. 前言

  12 factor app是SAAS(Software As A Service)的基本原则,也是在我们日常工作中需要遵循的原则。其原文链接在文末给出,因为有对应的中文版(虽然翻译的不是很好)所以本文主要不在于复制粘贴一遍内容,而是对其内容的归纳和理解,以及一些自己遇到的事例经验。12 factor app核心思想包括:

  • 版本控制:使用标准化流程自动配置,从而使新的开发者花费最少的学习成本加入这个项目。
  • 移植性:和操作系统之间尽可能的划清界限,在各个系统中提供最大的可移植性。
  • 易于部署:适合部署在现代的云计算平台,从而在服务器和系统管理方面节省资源。
  • 开发和生产的一致性:将开发环境和生产环境的差异降至最低,并使用持续交付实施敏捷开发。
  • 扩展性:可以在工具、架构和开发流程不发生明显变化的前提下实现扩展。

下面详细讲解12个基本原则。

二. 12个基本原则和理解

  1. 基准代码

  该部分主要有几点注意事项

(1)版本控制工具的使用对于任何工程均十分重要,如Git, Mercurial, Subversion。这些工具是多个程序员协同完成一个产品必备的管理工具和记录工具
(2)基准代码和应用是一一对应的关系,不存在一对多或者多对一
(3)基准代码可以部署为很多不同的版本,举个例子,游戏有当前运行供给玩家的版本,有正在开发的新版本,有体服测试版本,有供给测试的版本等等等等。

  1. 依赖

  SAAS要求应用指明显示依赖清单,并且不依赖清单外的任何库。这条原则很容易理解:所有在Linux有过安装应用缺依赖库的都曾因此烦躁过。而采用这条原则的如如Ruby/Bundler 下使用 bundle install,而 Clojure/Leiningen 则是 lein deps,一条指令直接打包安装无需烦恼,是多么令人心情愉悦的事。

  1. 配置

  因为一个基准代码可能存在不同的部署,而不同的部署可能有着不同的配置,比如数据库的使用,第三方证书,域名等等,因此需要考虑如何保证基准代码和配置的隔离,即该应用的基准代码是否可以立刻开源,而不用担心会暴露任何敏感的信息。鉴于此,此处给出的推荐解决方法是将配置信息存储于环境变量之中,从而实现在不同的部署中方便的修改又不需要因此修改基准代码的内容。

  1. 后端服务

  该条原则要求代码对使用何种后端服务不敏感,即解耦合或者松耦合,随时修改后端的策略对用户使用应用并没有任何影响,该条原则可以说是后端开发必备原则了。将本地/第三方服务均视为抽象的资源,资源的增删修改对上层毫无影响。

  1. 构建、发布和运行

  将基准代码转化为商用部署需要严格执行这三个步骤:

  • 构建阶段 是指将代码仓库转化为可执行包的过程。构建时会使用指定版本的代码,获取和打包 依赖项,编译成二进制文件和资源文件。
  • 发布阶段 会将构建的结果和当前部署所需 配置 相结合,并能够立刻在运行环境中投入使用。
  • 运行阶段 (或者说“运行时”)是指针对选定的发布版本,在执行环境中启动一系列应用程序 进程。

  本条原则是商业化产品的标准开发路线,属于通用的基本原则。

  1. 进程

  本条原则在于避免进程间通信或者资源共享。这样做既是为了安全考虑,也是为了程序的高效和健壮性考虑。而所有需要使用的资源,统一交给后端存入硬盘和数据库中实现。
  这一条其实存在一些争议,对于微服务场景适用,但是对于一些其他应用不一定适用,不属于通用原则。

  1. 端口绑定

  本条取名为端口绑定其实不大恰当,其本意包括了两点:(1)SAAS应用不应该依赖于任何其他网络服务器,而是自己绑定端口运行 (2)互联网应用 通过端口绑定来提供服务 ,并监听发送至该端口的请求

  1. 并发

  12-Factor 应用的进程主要借鉴于 unix 守护进程模型 。开发人员可以运用这个模型去设计应用架构,将不同的工作分配给不同的 进程类型 。例如,HTTP 请求可以交给 web 进程来处理,而常驻的后台工作则交由 worker 进程负责。

  本条原则建立在原则6的基础上,由于这种特殊的架构,使得扩展性极佳,在微服务领域属于最基本的原则。也可以借鉴于其他领域使用。

  1. 易处理

  本条原则要求代码有着快速启动和优雅终止的健壮性。首先,代码的启动时间应该尽可能地小,因此在出错时可以快速地重启,也更利于扩展性。其次,当收到终止信号SIGTERM时,则“优雅”的退出。这里的“优雅”指的是:
(1)对网络进程来说停止监听端口,执行完当前任务后立刻停止工作
(2)对工作线程来说将当前任务退回队列,例如,RabbitMQ 中,worker 可以发送一个NACK信号。 Beanstalkd 中,任务终止并退回队列会在worker断开时自动触发。有锁机制的系统诸如 Delayed Job 则需要确定释放了系统资源。此类型的进程所隐含的要求是,任务都应该 可重复执行 , 这主要由将结果包装进事务或是使重复操作 幂等 来实现。
(3)在意外死亡时,保持健壮。这里推荐使用健壮的后端队列,如Beanstalkd。

  1. 开发环境和线上环境等价

  实际上开发和线上环境存在差异是很正常的事,主要体现在:

  • 时间差异: 开发人员正在编写的代码可能需要几天,几周,甚至几个月才会上线。
  • 人员差异: 开发人员编写代码,运维人员部署代码。
  • 工具差异: 开发人员或许使用 Nginx,SQLite,OS X,而线上环境使用 Apache,MySQL 以及 Linux。

为了缩小差异,大致需求如下:

  • 缩小时间差异:开发人员可以几小时,甚至几分钟就部署代码。
  • 缩小人员差异:开发人员不只要编写代码,更应该密切参与部署过程以及代码在线上的表现。
  • 缩小工具差异:尽量保证开发环境以及线上环境的一致性。

为了实现这些,需要开发人员做到使用和线上一致的环境进行开发,而不是为了方便使用轻量级应用。

  1. 日志

  把日志当作事件流,应用本身不考虑自己的输出流,而是在此之外采用额外处理程序用于查看或长期存档。这种做法的好处在于统一了日志的处理,并单独分离了功能,易于后续优化和修改。

  1. 管理进程

  进程构成(process formation)是指用来处理应用的常规业务(比如处理 web 请求)的一组进程。与此不同,开发人员经常希望执行一些管理或维护应用的一次性任务,例如:

  • 运行数据移植(Django 中的 manage.py migrate, Rails 中的 rake db:migrate)。
  • 运行一个控制台(也被称为 REPL shell),来执行一些代码或是针对线上数据库做一些检查。大多数语言都通过解释器提供了一个 REPL 工具(python 或 perl) ,或是其他命令(Ruby 使用 irb, Rails 使用 rails console)。
  • 运行一些提交到代码仓库的一次性脚本。

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

参考文献

【1】https://12factor.net/

发布了129 篇原创文章 · 获赞 15 · 访问量 4万+

猜你喜欢

转载自blog.csdn.net/u013354486/article/details/104184307
app
今日推荐