The Twelve-Factor App 实践
The Twelve-Factor App
《The Twelve-Factor App》定义了一个优雅的互联网应用在设计过程中,尤其是在设计SAAS服务时,需要遵循的一些基本原则。本文为该设计原则的读书笔记,并备注了自己在项目实践中的一些实施经验,在后续的工作中,会陆续加入更多的落地资料和心得。
指导思想
使用标准化流程自动配置,从而使新的开发者花费最少的学习成本加入这个项目。
和操作系统之间尽可能的划清界限,在各个系统中提供最大的可移植性。
适合部署在现代的云计算平台,从而在服务器和系统管理方面节省资源。
将开发环境和生产环境的差异降至最低,并使用持续交付实施敏捷开发。
可以在工具、架构和开发流程不发生明显变化的前提下实现扩展。
实践十二条准则
I. 基准代码
一份基准代码,多份部署。
基于这个原则,在项目实施时,代码仓库的管理需要注意:在存在多个module(业务模块),且每个module独立部署时(表现为多个进程),不要将这些module建立在同一个git仓库下,因为更改其中一个module,势必会更改基准代码,从而可能影响到其他module。
项目中,可以将“多份部署”对应到多个branch,不同的部署环境对应不同的代码分支:master分支是基准代码分支,所有代码分支均是从master分支迁出;release分支为当前发布中的分支,对应到“测试环境”、‘预发布环境’和‘生产环境’;dev(每个任务会迁出一个开发分支)分支是开发人员本地的开发分支,对应部署到本地开发环境。
实际操作中,可以灵活处理,开发人员也可以将dev分支直接发布到“测试环境”,供测试人员测试。
各个分支的代码要么被废弃掉,要么合并至master。基本的合并路径为:dev --> release --> master。
II. 依赖
显式声明依赖关系。
III. 配置
在环境中存储配置。
实际项目中,遵循CI规范,将所有可变的配置项(含系统配置和应用配置)全部放置到config目录,且每个部署环境对应一个目录,将具体的配置信息放置到对应环境目录中,由CI(持续集成)工具根据当前部署环境将配置信息打包进去;结构示意如下:
-- config
---- dev
---- fat
---- stg
----prd
IV. 后端服务
把后端服务当作附加资源。
实际项目中,将数据库、缓存、队列等当着资源处理,动态配置各个环境的资源地址和信息;但是未做到服务化,无法运行时中动态切换资源地址。
V. 构建,发布,运行
严格分离构建和运行。
基准代码 转化为一份部署(非开发环境)需要以下三个阶段:构建、发布、运行。
“构建”使用CI工具完成的,所以III是V的基础;“发布”和“运行”是由CD(持续发布)工具来完成。
实际项目中,“版本”表现为“变更单”。每次“构建”会创建一个变更单,变更单一旦创建,其对应的代码内容不能被更改;变更单可以在各个环境之间流转:dev > fat > stg > prd,如果发现版本内容有bug,可以回退版本,将运行时变更单更改为上一个稳定的变更单。
VI. 进程
以一个或多个无状态进程运行应用。
对于分布式架构,无状态服务是基本要求,原因在于:如果服务在自身维护状态,势必影响到服务的扩展性,那么分布式架构的优势就大打折扣。
实际项目中,业务服务module不会持有状态,将“状态”交由统一存储来管理。比如:SSO机制来统一管理“用户会话”(user session)内容,“用户会话”由登录服务写入SSO的存储中,各个业务module调用SSO的“会话校验”(checkLogin)服务完成会话控制。
VII. 端口绑定
通过端口绑定提供服务。
这一点很好理解。服务间通过调用来解耦,且端口绑定的形式使得每个服务都独享一个端口,利于服务的管理和维护。
延伸一下:在领域驱动设计(Domain Driven Design)中,Eric Evans提出的“开发主机服务”(Open Host Service)的实质也是这个意思。可参考《领域驱动设计-软件核心复杂性应对之道》P276。
VIII. 并发
通过进程模型进行扩展。
任何计算机程序,一旦启动,就会生成一个或多个进程。互联网应用采用多种进程运行方式。
采用多种进程模型的目的在于更好扩展,不同职责的服务交由不同的进程来负责。
在进程模型上,java应用表现为单进程多线程的形式。因此,我们通常将不同职责的服务独立部署。比如:restful服务、业务job、消息处理等等。
其中restful服务为web服务,对客户端提供业务服务,业务job和消息处理为后台运行服务。
实际项目中通常将业务job和消息处理放置在一个组件中完成,这是不友好的。
延伸一下:依据DDD的设计思想,我们需要将业务逻辑内聚到业务领域中,同一业务领域不应当存在多份。通常意义上,我们会将业务领域交由restful服务来管理,因此,在job和消息处理组件中不应当包含业务领域代码,推荐的方式是让他们调用restful服务完成业务逻辑处理。
上述实践的示意图如下:

IX. 易处理
快速启动和优雅终止可最大化健壮性。
实际中,job进程的快速终止,可能造成“重复跑批”的情况,这时候需要REST-Service提供“幂等”服务,以确保重复跑批不会给业务代码一致性问题。
服务 “幂等性”的要求可以从两个角度去理解:
对同一个服务,多次发起同样请求(请求内容),服务对业务实体状态的影响保持一致,这里的一致可以是“不变”,或者说是“符合业务逻辑的改变”;
对于服务调用方,对同一服务多次发起同样请求,得到的响应是一致的。
X. 开发环境与线上环境等价
尽可能的保持开发,预发布,线上环境相同。
这个原则带来的好处主要在线上排障的时候,很多时候,生产环境发生故障或者bug时,第一时间会在预发布或者测试环境进行问题复现,而要做到这一点,必须保证环境一致。
XI. 日志
把日志当作事件流。
日志的重要性不言而喻,日志能够反映出系统和应用运行时的状况,尤其在出现故障或者bug时,及其有用。
实际项目中,通常将日志按照规范格式输出到日志文件,通过各种日志插件将日志内容汇聚到日志分析系统,日志分析系统完成存储、计算,最后通过UI展示给使用者。
使用得比较广泛的日志工具如:ELK。
XII. 管理进程
后台管理任务当作一次性进程运行。
延伸阅读
《The Twelve-Factor在Cloud Native时代是否依然适用?》(http://www.infoq.com/cn/news/2016/07/Heroku-CloudNative)
Eric Evans的《领域驱动设计-软件核心复杂性应对之道》
The Twelve-Factor App 实践的更多相关文章
- 12 Factor App
The Twelve-Factor App Introduction In the modern era, software is commonly delivered as a service: c ...
- 使用Cordova框架把Webapp封装成Hybrid App实践——Android篇
公司没有IOS和没有安卓开发人员,前端后端都是需要自己玩前几天技术经理说有一个需求要把webapp封装成Hybrid App,现已完成.记录一下从中遇到的问题和需要用到的开发环境的配置 将Webapp ...
- The Twelve-Factor Container
转自:https://medium.com/notbinary/the-twelve-factor-container-8d1edc2a49d4?%24identity_id=550978996201 ...
- 学用HBuilder开发App的看过来
自己的呕心沥血之作吧,花了一年时间,系统介绍HTML5 App开发的相关技术. 越来越多的公司采用HTML5来快速开发移动跨平台App,它支持当前市场流行的移动设备. 本书主要介绍了HTML5在移动A ...
- 12 Factor CLI Apps
CLIs are a fantastic way to build products. Unlike web applications, they take a small fraction of t ...
- 谷歌推出全新Android开发语言Sky:让App更流畅
土豆网同步更新:http://www.tudou.com/plcover/VHNh6ZopQ4E/ 使用HTML 创建Mac OS App 视频教程. 官方QQ群: (1)App实践出真知 434 ...
- 《HTML开发Mac OS App 视频教程》 第001讲、入门教程
土豆网同步更新:http://www.tudou.com/plcover/VHNh6ZopQ4E/ 使用HTML 创建Mac OS App 视频教程. 官方QQ群: (1)App实践出真知 434 ...
- DevOps 工程师成长日记系列二:配置
原文地址:https://medium.com/@devfire/how-to-become-a-devops-engineer-in-six-months-or-less-part-2-config ...
- 161027、Java 中的 12 大要素及其他因素
对于许多人来说,"原生云"和"应用程序的12要素"是同义词.本文的目的是说有很多的原生云只坚持了最初的12个因素.在大多数情况下,Java 能胜任这一任务.在本 ...
随机推荐
- 玩转PS路径,轻松画logo!
轻松画图标!教你一分钟玩转PS路径描边 推荐: cyRotel 2014/11/24 in PS 教程 & 设计文章 @Micu设计 :Photoshop的路径工具和钢笔工具 ...
- [转载]python 详解re模块
原文地址:python 详解re模块作者:Rocky 正则表达式的元字符有. ^ $ * ? { [ ] | ( ) .表示任意字符 []用来匹配一个指定的字符类别,所谓的字符类别就是你想匹配的一个字 ...
- bootstrap导航条+模态对话框+分页样式
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content ...
- 201521123068《Java程序设计》第4周学习总结
1. 本周学习总结 1.1 尝试使用思维导图总结有关继承的知识点. 点击查看->高清脑图 1.2 使用常规方法总结其他上课内容. 答:学习继承与多态的知识,了解它们之间的关系:super.ext ...
- 201521123067 《Java程序设计》第2周学习总结
1. 本周学习总结 ●本周主要学习了java的基本语法,从中我知道了java中的变量类型以及关于类型转换的问题,而且学会了通过import引用包. ●通过本周的学习,我学会了使用数组,包括对数组的创建 ...
- 201521123112《Java程序设计》第2周学习总结
1.本周学习总结 本周在课堂面授课粗略讲了<Java学习笔记>中的第三章,其内容大部分都与上学期学习的数据结构差不多,所以只是粗略的复习了一下就带过,然后通过将PTA上的实验便于我们本周的 ...
- 201521123060 《Java程序设计》第12周学习总结
1.本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结多流与文件相关内容. 2.书面作业 将Student对象(属性:int id, String name,int age,double ...
- 本地不安装oracle,plsql照样用起来
对于配置有限的电脑,不安装oracle需要使用plsql怎么设置才可以使用呢 一.首先下载一个instantclient (Oracle提供的一个较为轻量级的客户包) 据说plsql不支持64位的in ...
- 远程无法访问linux Mysql解决方案
在网上有很多关于这个的解决方案,我也采用了 写的比较详细的如: 1. 改表法.可能是你的帐号不允许从远程登陆,只能在localhost.这个时候只要在localhost的那台电脑,登入mysql后,更 ...
- 15 Validation
一.模型选择问题 如何选择? 视觉上 NO 不是所有资料都能可视化;人脑模型复杂度也得算上 通过Ein NO 容易过拟合;泛化能力差 通过Etest NO 能保证好的泛化,不过往往没法提前获得测试资料 ...