Spring Cloud学习笔记之12-Factor

来源:互联网 发布:mac 重新安装jenkins 编辑:程序博客网 时间:2024/05/02 02:15

Spring Cloud学习笔记之12-Factor:

Spring Cloud介绍

  Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智能路由,微代理,控制总线,一次性令牌,全局锁,领导选举,分布式会话,集群状态)。分布式系统的协调导致锅炉板模式,并且使用Spring Cloud开发人员可以快速站起来实现这些模式的服务和应用程序。他们将在任何分布式环境中工作良好,包括开发人员自己的笔记本电脑,裸机数据中心,以及Cloud Foundry等托管平台。

  如今,软件通常会作为一种服务来交付,它们被称为网络应用程序,或软件即服务(SaaS)。12-Factor 为构建如下的 SaaS 应用提供了方法论:

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

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

12-Factor学习:

I. 基准代码:一份基准代码,多份部署

  在类似 SVN 这样的集中式版本控制系统中,基准代码就是指控制系统中的这一份代码库;而在 Git 那样的分布式版本控制系统中,基准代码则是指最上游的那份代码库。

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

  • 一旦有多个基准代码,就不能称为一个应用,而是一个分布式系统。
  • 多个应用共享一份基准代码是有悖于 12-Factor 原则的。解决方案是将共享的代码拆分为独立的类库,然后使用 依赖管理 策略去加载它们。
    每个应用只对应一份基准代码,但可以同时存在多份部署。每份 部署 相当于运行了一个应用的实例。

codebase-deploys

II. 依赖:显式声明依赖关系

  12-Factor规则下的应用程序不会隐式依赖系统级的类库。 它一定通过依赖清单,确切地声明所有依赖项。此外,在运行过程中通过依赖隔离工具来确保程序不会调用系统中存在但清单中未声明的依赖项。这一做法会统一应用到生产和开发环境。

  显式声明依赖的优点之一是为新进开发者简化了环境配置流程。新进开发者可以检出应用程序的基准代码,安装编程语言环境和它对应的依赖管理工具,只需通过一个 构建命令 来安装所有的依赖项,即可开始工作。

III. 配置:在环境中存储配置

  12-Factor 要求代码和配置严格分离,就是将配置排除在代码之外。

  12-Factor推荐将应用的配置存储于环境变量中(env vars,env)环境变量可以非常方便地在不同的部署间做修改,却不动一行代码;与配置文件不同,不小心把它们签入代码库的概率微乎其微;与一些传统的解决配置问题的机制(比如 Java 的属性配置文件)相比,环境变量与语言和系统无关。

IV. 后端服务:把后端服务当作附加资源

  后端服务是指程序运行所需要的通过网络调用的各种服务,如数据库(MySQL,CouchDB),消息/队列系统(RabbitMQ,Beanstalkd),SMTP 邮件发送服务(Postfix),以及缓存系统(Memcached)。
  12-Factor 应用不会区别对待本地或第三方服务。对应用程序而言,两种都是附加资源,通过一个url或是其他存储在配置中的服务定位/服务证书来获取数据。12-Factor 应用的任意部署,都应该可以在不进行任何代码改动的情况下,将本地MySQL数据库换成第三方服务(例如 Amazon RDS)。类似的,本地SMTP服务应该也可以和第三方SMTP服务(例如Postmark)互换。上述2个例子中,仅需修改配置中的资源地址。

attached-resources

V. 构建,发布,运行:严格分离构建和运行

  基准代码 转化为一份部署(非开发环境)需要以下三个阶段:

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

  12-facfor 应用严格区分构建,发布,运行这三个步骤。举例来说,直接修改处于运行状态的代码是非常不可取的做法,因为这些修改很难再同步回构建步骤。

release

  部署工具通常都提供了发布管理工具,最引人注目的功能是退回至较旧的发布版本。

  新的代码在部署之前,需要开发人员触发构建操作。但是,运行阶段不一定需要人为触发,而是可以自动进行。如服务器重启,或是进程管理器重启了一个崩溃的进程。因此,运行阶段应该保持尽可能少的模块,这样假设半夜发生系统故障而开发人员又捉襟见肘也不会引起太大问题。构建阶段是可以相对复杂一些的,因为错误信息能够立刻展示在开发人员面前,从而得到妥善处理。

VI. 进程:以一个或多个无状态进程运行应用

  运行环境中,应用程序通常是以一个和多个进程运行的。

  12-Factor 应用的进程必须无状态且无共享。任何需要持久化的数据都要存储在后端服务内,比如数据库。

  对于有状态服务,还是无状态服务,其判断是指两个来自相同发起者的请求在服务器端是否具备上下文关系。如果是状态化请求,那么服务器端一般都要保存请求的相关信息(session、cookie),每个请求可以默认地使用以前的请求信息(请求信息从session中获取)。而对于无状态请求,服务器端所能够处理的过程必须全部来自于请求所携带的信息(请求信息全部从参数中获取),以及其他服务器端自身所保存的、并且可以被所有请求所使用的公共信息。

VII. 端口绑定:通过端口绑定提供服务

  12-Factor 应用完全自我加载而不依赖于任何网络服务器就可以创建一个面向网络的服务。互联网应用通过端口绑定来提供服务,并监听发送至该端口的请求。

  本地环境中,开发人员通过类似

http://localhost:8080/

的地址来访问服务。在线上环境中,请求统一发送至公共域名而后路由至绑定了端口的网络进程。

  通常的实现思路是,将网络服务器类库通过依赖声明载入应用。例如,Java 以及其他基于 JVM 语言的 Jetty。完全由用户端,确切的说应该是应用的代码,发起请求。和运行环境约定好绑定的端口即可处理这些请求。

VIII. 并发:通过进程模型进行扩展

  任何计算机程序,一旦启动,就会生成一个或多个进程。互联网应用采用多种进程运行方式。例如,PHP 进程作为 Apache 的子进程存在,随请求按需启动。Java进程则采取了相反的方式,在程序启动之初 JVM 就提供了一个超级进程储备了大量的系统资源(CPU和内存),并通过多线程实现内部的并发管理。上述2个例子中,进程是开发人员可以操作的最小单位

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

process-types

IX. 易处理:快速启动和优雅终止可最大化健壮性

  12-Factor 应用的 进程 是 易处理(disposable)的,意思是说它们可以瞬间开启或停止。

  进程应当追求最小启动时间。 理想状态下,进程从敲下命令到真正启动并等待请求的时间应该只需很短的时间。

  进程一旦接收终止信号(SIGTERM)就会优雅的终止 。就网络进程而言,优雅终止是指停止监听服务的端口,即拒绝所有新的请求,并继续执行当前已接收的请求,然后退出。此类型的进程所隐含的要求是HTTP请求大多都很短(不会超过几秒钟),而在长时间轮询中,客户端在丢失连接后应该马上尝试重连。

  对于 worker 进程来说,优雅终止是指将当前任务退回队列。

  进程还应当在面对突然死亡时保持健壮,例如底层硬件故障。虽然这种情况比起优雅终止来说少之又少,但终究有可能发生。一种推荐的方式是使用一个健壮的后端队列,例如 Beanstalkd ,它可以在客户端断开或超时后自动退回任务。

X. 开发环境与线上环境等价:尽可能的保持开发,预发布,线上环境相同

开发环境(即开发人员的本地部署)和线上环境(外部用户访问的真实部署)之间存在着很多差异。这些差异表现在以下三个方面:

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

12-Factor 应用想要做到持续部署就必须缩小本地与线上差异。 再回头看上面所描述的三个差异:

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

将上述总结变为一个表格如下:

传统应用 12-Factor 应用 每次部署间隔 数周 开发人员 vs 运维人员 不同的人 开发环境 vs 线上环境 不同

XI. 日志:把日志当作事件流

  日志使得应用程序运行的动作变得透明。在基于服务器的环境中,日志通常被写在硬盘的一个文件里,但这只是一种输出格式。

  日志应该是事件流的汇总,将所有运行中进程和后端服务的输出流按照时间顺序收集起来。尽管在回溯问题时可能需要看很多行,日志最原始的格式确实是一个事件一行。日志没有确定开始和结束,但随着应用在运行会持续的增加。

  12-factor应用本身从不考虑存储自己的输出流。不应该试图去写或者管理日志文件。相反,每一个运行的进程都会直接的标准输出(stdout)事件流。开发环境中,开发人员可以通过这些数据流,实时在终端看到应用的活动。

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

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

  12-factor 尤其青睐那些提供了 REPL shell 的语言,因为那会让运行一次性脚本变得简单。在本地部署中,开发人员直接在命令行使用 shell 命令调用一次性管理进程。在线上部署中,开发人员依旧可以使用ssh或是运行环境提供的其他机制来运行这样的进程。

阅读全文
0 0
原创粉丝点击