写点什么

The Twelve-Factor 在 Cloud Native 时代是否依然适用?

  • 2016-07-19
  • 本文字数:3547 字

    阅读完需:约 12 分钟

按语

Heroku 是云应用平台的先驱,从对外提供服务以来,他们已经有上百万应用的托管和运营经验。其创始人 Adam Wiggins 根据这些经验,提出了十二要素应用宣言 。The Twelve-Factor App 定义了一个优雅的互联网应用在设计过程中,需要遵循的一些基本原则。

不过, The Twelve-Factor 是在特定的时期,针对特定的平台实践所总结出来的。12 元素依然璀璨,很多原则依然具有普适性;但是在应用全面迁移到云端的今天,Cloud Native 时代的应用开发,需要有更多与时俱进的实践新原则。The Twelve-Factor 的哪些原则依然是适用的?哪些在实践需要与时俱进?这些都是众多Cloud Native 的实践者需要探求的答案。

新原则1:微服务应该以无状态的方式运行

The Twelve-Factor 指出一个应用在运行时,应该以一个或者多个无状态的进程来运行。进程之间需要做到无状态,并且无共享。任何需要持久化的数据,都应该写入到后端服务中,譬如数据库。这一原则,目的是避免进程和进程之间的耦合。让每一个进程,能够独立于其他实体单独构建和运行。

在很多在线系统中,会使用 session(会话)来传递当前的状态。当被调用方接收到 session 后,会将它保存下来,后续的请求,都会被路由到这个服务中。这时请求和请求之间,会有严格的调用顺序。Cloud Native 的实践原则是需要避免这种情况。

在 Cloud Native 理念中,每一个功能实体实际上是以一个微服务的形式运行的。微服务是一个单独的自治系统,它可以不依赖其他服务而单独存在。所有的微服务,都应该是以一种无状态的接口对外提供服务(譬如 Restful API)。微服务自身不应该保存任何的状态。如果微服务需要持续地保存数据,应该采用的做法是:调用服务化的存储,将数据保存在另一个存储服务里面。微服务之所以小块头能发挥大能量,正是源于无状态的设计从而保证可以同时由多个实例提供服务,让服务能力能够自由的伸缩。

当然,在实际的实践过程中,特别是针对大的系统,很难做到完全无状态的拆分。对一个完整的微服务架构,会分为事务性服务和存储型服务。通常说来,事务性服务需要做到无状态设计;所有的持久化数据,可以通过存储型服务来进行存储和读取。存储型服务尽量使用云端提供的集中式的服务化存储能力,譬如云端的对象存储。

新原则 2:应通过配置来唯一定义一个系统

The Twelve-Factor 的第五条原则提到了应用需要严格区分构建、发布、运行这三个步骤:譬如直接修改处于运行状态的代码是非常不可取的做法,因为这些修改很难再同步回构建步骤。The Twelve-Factor 的第五原则,很好的规范了一个应用从开发到运营的标准化的操作流程。但是第五原则,只是保证了应用源码的唯一性。很多时候,一个系统的故障,并不仅仅是由源码导致的,很大一部分故障,和配置以及环境的变化存在关系。所以 The Twelve-Factor 的第五原则在 Cloud Native 的理念下,需要与时俱进。

Cloud Native 在实践时,是通过 Docker+ 微服务的方式去实现的。Docker 实现了 Build、Ship、Run 的统一。任何系统,都是可以通过一些配置,唯一定义出来的。当这个系统定义出来以后,应该是能够重构出来,不随着时间、运行环境或依赖条件变化而变化。同时,这个系统不管处于开发阶段、测试阶段还是运营阶段,其状态都是唯一的。

譬如,在实践过程中,可以通过 Docker Compose 的 YAML 文件唯一的定义一个容器间互联的系统。这个系统的配置是唯一确定的,可以在任何的容器环境下去执行。会有一个唯一的仓库 (Docker Registry) 来存储镜像。所有的镜像,都是通过 Dockerfile 唯一定义的。当触发了源码的变更以后,这个系统的各个组件可以自动的去构建,然后更新到“仓库”,在通过 Docker Compose 组装起来。只要遵循了这套标准化的流程,系统不会区分开发环境,测试环境,运营环境。所有的东西,就只有一个环境;这个环境,是唯一的、可定义的。

在实践这条原则时,需要遵循以下几条规范:
• 需要有唯一的源码库,并保证任何的变更都是在源码托管库中进行
• 通过 Dockerfile 来构建镜像而非通过运行中的容器来打包镜像
• 通过配置来定义容器之间的连接关系而非手动的部署

新原则 3:应该使用服务化存储

The Twelve-Factor 有一条原则是“把后端服务 (backing services) 当作附加资源”,后端服务是指程序运行所需要的通过网络调用的各种服务,如数据库(MySQL,CouchDB)、消息 / 队列系统(RabbitMQ,Beanstalkd)、SMTP 邮件发送服务(Postfix)以及缓存系统(Memcached)。这些都是作为“资源”来对待,目的是为了保证模块之间的松耦合。

作为一个系统中最重要的角色,存储模块当然必不可少。存储有很多种类:块存储、对象存储、数据库存储、缓存。传统上,我们接触比较多的是块存储。在 Cloud Native 的理念下,一个系统中,所有的组成实体都可以服务化。有事务型的服务,也有存储型服务。微服务之间是一种松散耦合的关系。服务和服务之间,是没有任何耦合关系的,只有调用关系。当一个服务,需要存储数据怎么办?一种方案是把数据存在在服务内部,这样势必导致了服务存在状态,从而限制了服务的横向扩展的能力。前面一节,我们提到了一个重要原则是,事务型服务尽量保证是无状态的。所以当一个事务型服务需要存储数据时,应该是将数据存储到另外一个存储型服务中,通过存储型服务提供的标准接口和协议读取或者写入数据。在云上我们通常使用的对象存储,或者云端的数据库,就是这种服务化的存储方式。

使用服务化存储,可以带来三个方面的好处:
• 将存储和逻辑处理分离,让系统能够自动化的重构出来
• 统一存储,不需要单独考虑服务内部存储的容错、备份等机制
• 做到事务型服务无状态,便于横向扩展

总结

The Twelve-Factor APP 作为网络应用开发的最佳实践原则,的确具有强大的生命力。每一条原则都是应用开发的珠玑。但是技术总是不停的发展,在云的时代,所有的应用都会迁移到云端,完全基于云的架构设计和开发模式需要一套全新的理念去承载。这个时候,Cloud Native 的思想应运而生。在 Cloud Native 时代,The Twelve-Factor 的核心思想依然璀璨,但是应该随着这种新的理念去延伸、发展。文章提到的三条新原则,也正是 The Twelve-Factor 的延伸。未来,随着 Cloud Native 思想在开发中使用越来越广泛,一定会延伸出更多的实践的原则。

资料附:Cloud Native 时代 12 新要素

  1. 从一个代码库部署到多个环境——一个代码库,包括生产环境软件包,确保了单一的信任源,从而保证了更少的配置错误和更强的容错和复原能力。
  2. 依赖管理是声明式的——云平台根据这些声明管理依赖,确保云应用所需的库和服务。
  3. 配置信息保存在环境中——环境变量是一种清楚、容易理解和标准化的配置方法,特别适合用不同编程语言编写的无状态应用的使用。
  4. 将后台服务视为附加的资源——将每一种资源都视为一种远程的资源,应用因此具有容错和复原能力,因为它一方面要求编码时就要考虑资源不可用的情况,另外一方面也增强微服务方法的好处。
  5. 区分构建、发布和运行阶段——Cloud Native 应用的构建流程把大部分发布配置挪到开发阶段,包括实际的代码构建和运行应用所需的生产环境配置。
  6. 作为无状态进程运行——尽量保持应用栈每一层的轻量级,保证 Cloud Native 基础设施的速度和效率。
  7. 通过端口绑定对外暴露服务——Cloud Native 应用的服务接口优先选择 HTTP API 作为通用的集成框架。
  8. 通过添加无状态进程实现横向扩展——强调无状态、无共享的设计,这意味着依赖底层平台就能实现横向扩展,不需要技术难度高的多线程编码。
  9. 快速地启动,优雅地关停——假设任何进程随时都能启动和关停。
  10. 开发、预发布和生产环境运行同样的应用和依赖配置——由于强调自动化和在每个阶段使用同一个云平台,如果每个人用同样的服务器配置,那么“应用在我这里是可以的”就意味着在其他人或者环境那里也是可以的。
  11. 日志输出到标准输出,方便日志聚合和事件响应——当日志是由云平台而不是应用包含的库处理时,日志处理机制必须保持简单。
  12. 临时任务作为短时进程运行——在 Cloud Native 中,管理任务也是一个进程,而不是特别的工具;同样重要的是,管理任务的进程不应使用秘密的 API 或者内部机制。

作者简介

刘永峰,腾讯云高级产品经理,布道师,十余年的产品及研发管理经验。国内最早一批从事可信计算研究的探索者。曾就职于中兴通讯,负责流媒体 Server 后台架构设计,Linux 内核相关的研究。2011 年起加入腾讯,一直从事公有云的产品设计,云计算市场趋势分析和研究,云计算技术的推广与普及。在技术和产品领域均具有丰富的行业经验。目前主要关注 Docker,微服务,Cloud Native, 企业云化趋势等相关领域。


感谢木环对本文的审校。

给InfoQ 中文站投稿或者参与内容翻译工作,请邮件至 editors@cn.infoq.com 。也欢迎大家通过新浪微博( @InfoQ @丁晓昀),微信(微信号: InfoQChina )关注我们。

2016-07-19 19:002379

评论

发布
暂无评论
发现更多内容

Qt | 实现自定义手机号输入框控件

YOLO.

qt 10月月更 C++

Node.js TLSSocket 库里涉及到的证书链的概念简介

汪子熙

JavaScript node.js 后端开发 SAP 10月月更

欢迎奥看科技加入openGauss社区

openGauss

Github 访问量过百万!阿里内部springcloud手册, 实至名归

Geek_0c76c3

Java 数据库 程序员 开发

Java的跨平台和环境搭建

共饮一杯无

jdk java基础 10月月更 java环境搭建

【Java深入学习】join再理解

Geek_65222d

10月月更

【LeetCode】优势洗牌Java题解

Albert

LeetCode 10月月更

如何实时、高效地处理如此海量的路况数据

华为云开发者联盟

人工智能 华为云 图片处理 智慧交通 企业号十月 PK 榜

云和恩墨大讲堂 x openGauss Meetup x 鲲鹏生态孵化营(上海站)圆满落幕

openGauss

cuda+cudnn ubuntu20安装

Ayosh

如何使用流程 中的 DataObject 并为流程设置租户

江南一点雨

Java springboot workflow flowable

MFC|CCombobox控件修改编辑框光标显示位置

中国好公民st

c c++ 10月月更

欢迎海天起点加入openGauss社区

openGauss

IDEA的Docker插件实战(Dockerfile篇)

程序员欣宸

Docker IDEA 10月月更

Python进阶(五)浅谈python匿名函数及编写无参数decorator

No Silver Bullet

Python 10月月更 匿名函数 无参数decorator

LinkedList源码分析(二)

知识浅谈

linkedlist 10月月更

DDD 建模案例分享

Bright

敏捷 DDD TDD

不要小看一个Redis!阿里最新开源Redis核心原理+应用实践,涵盖了Redis的所有操作

程序员小毕

面试 程序人生 中间件 Java后端 redis 底层原理

说说 Spring 定时任务如何大规模企业级运用

阿里巴巴云原生

spring 阿里云 云原生

hashmap常见面试题

普罗米修斯

10月月更

欢迎新大陆软件加入openGauss社区

openGauss

首份把架构三原则拆开来讲的“架构师宝典”,电子版已上线

Geek_0c76c3

Java 数据库 开源 程序员 开发

大数据ELK(十八):Beats 简单介绍和FileBeat工作原理

Lansonli

10月月更 大数据ELK

Python进阶(七)浅谈python3和Python2的区别

No Silver Bullet

Python3 区别 10月月更 Python2

10项任务助你落地架构课程!

华仔

架构实战营

Java 隐藏 Word 文档中的特定段落

在下毛毛雨

从零开始学Graph Database:什么是图

华为云开发者联盟

人工智能 华为云 图数据库 图计算引擎 企业号十月 PK 榜

“智领医疗 数创未来”活动成功举办,海量数据携手openGauss为医疗数字化创新赋能

openGauss

Photoshop软件应用项目(二)

张立梵

设计师 ps 10月月更

C++ | 关于extern关键字的使用

YOLO.

qt 10月月更 C++

欢迎数造科技加入openGauss社区

openGauss

The Twelve-Factor在Cloud Native时代是否依然适用?_语言 & 开发_刘永峰_InfoQ精选文章