对于许多人来说,“原生云”和“应用程序的12要素”是同义词。本文的目的是说有很多的原生云只坚持了最初的12个因素。在大多数情况下,Java 能胜任这一任务。在本文中,我们将研究概念和代码示例,超越标准的12个因素的过程。 Kevin Hoffmann 最近在 O’Reilly 出版的书上提到了超越 12 个因素的应用。

1. 一个代码库

虽然少了一个特定的 Java 概念,这个因素一般是指单个代码库在源代码控制或管理一组的存储库是来自于一个共同的根。 获取单个代码库 使它能更清洁地构建,并在各种环境下推出任意数量不同的发布版本。当你的应用程序是由一打或者更多的代码库构成的,那么这就是最好的反面案例。当使用一个代码库来生产多种可以工作的应用程序,且目标在应用和代码库间是一种一对一的关系。操作从一个代码库就可以做到,这不是说没有挑战。有时,对一个团队或者组织来说,一个应用程序对应一个代码库是最简单的关系。

大部分Java开发人员(包括Groovy)会使用Maven和Gradle之类的工具。想要正确地地编译及执行项目,这些工具提供了描述依赖关系的方法。核心思想是允许开发人员描述依赖关系,并使用工具确保这些依赖关系被实现、打包进一个单独的二进制部署的构件中。Maven Shade或者 Spring Boot 这样的插件使你能够把应用和依赖关系绑定成一个单独的“uberjar” or “fat jar”文件中,这样就提供了隔离这些依赖关系的方法。

图1是Spring Boot应用的Maven编译文件pom.xml例子的一部分,它显示了开发人员所指定的依赖关系。

图1:  应用依赖POM.xml 的其中一部分

<parent>

    <groupId>org.springframework.boot</groupId>

    <artifactId>spring-boot-starter-parent</artifactId>

    <version>1.3.7.RELEASE</version>

    <relativePath/> <!-- lookup parent from repository

    -->

</parent>

<dependencies>

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-config</artifactId>

    </dependency>

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-eureka</artifactId>

    </dependency>

    <dependency>

        <groupId>org.springframework.cloud</groupId>

        <artifactId>spring-cloud-starter-zipkin</artifactId>

    </dependency>

图2是相同应用中列出的依赖关系的另外一部分。这展示了JARS文件被绑定到应用的uberjar中,并从可变的环境中隔离这些依赖关系。应用的构建依靠这些依赖关系而不是部署目标中可能产生冲突的类库。

图2: 部分maven依赖关系:示例项目树状关系

[INFO] Scanning for projects...

[INFO]

[INFO] ------------------------------------------------------------------------

[INFO] Building quote-service 0.0.1-SNAPSHOT

[INFO] ------------------------------------------------------------------------

[INFO]

[INFO] --- maven-dependency-plugin:2.10:tree (default-cli) @quote-service ---

[INFO] com.example:quote-service:jar:0.0.1-SNAPSHOT

[INFO] +- org.springframework.cloud:spring-cloud-starterconfig:jar:1.1.3.RELEASE:compile

[INFO] | +- org.springframework.cloud:spring-cloud-starter:jar:1.1.1.RELEASE:compile

[INFO] | | +- org.springframework.cloud:spring-cloud-context:jar:1.1.1.RELEASE:compile

[INFO] | | | \- org.springframework.security:springsecurity-crypto:jar:4.0.4.RELEASE:compile

[INFO] | | +- org.springframework.cloud:spring-cloud-commons:jar:1.1.1.RELEASE:compile

[INFO] | | \- org.springframework.security:spring-securityrsa:jar:1.0.1.RELEASE:compile

[INFO] | | \- org.bouncycastle:bcpkixjdk15on:jar:1.47:compile

[INFO] | | \- org.bouncycastle:bcprovjdk15on:jar:1.47:compile

[INFO] | +- org.springframework.cloud:spring-cloud-configclient:jar:1.1.2.RELEASE:compile

[INFO] | | \- org.springframework.boot:spring-boot-autoconfigure:jar:1.3.7.RELEASE:compile

[INFO] | \- com.fasterxml.jackson.core:jacksondatabind:jar:2.6.7:compile

[INFO] | \- com.fasterxml.jackson.core:jacksoncore:jar:2.6.7:compile

[INFO] +- org.springframework.cloud:spring-cloud-startereureka:jar:1.1.5.RELEASE:compile

[INFO] | +- org.springframework.cloud:spring-cloud-netflixcore:jar:1.1.5.RELEASE:compile

[INFO] | | \- org.springframework.boot:springboot:jar:1.3.7.RELEASE:compile

2. 编译, 发布, 运行

一个独立的代码库是通过编译构成并生成独立构件;然后和项目外部的配置信息进行合并。代码库随后被发布到云环境下运行。千万不要在运行期间改变代码。由于系统提供了使用相同方式把构件组装到一起的单独的位置,编译的思想在于自然地过渡到下一步的集成 (CI)。

现代的Java框架可以生成uberjars文件,或者更传统的WAR文件, 这些文件作为独立的容易集成的构件。发布阶段主要是合并外部的配置信息(参考下面的配置)和独立的项目构件以及像JDK,OS,和Tomcat这样的依赖。目的是生成可执行的、版本化的、可以撤销的发布版本。云平台拿到发布版本后使用一种严格独立的方式来处理运行阶段。

3. 配置

这一要素是具体化配置的形式,随着部署环境的变化有所不同。(开发, 演示, 生产). 配置信息无处不在: 分布在应用的代码中, 在如YAML这样的属性源文件中, Java属性, 环境变量, CLI参数, 系统参数, JNDI, 等等。有多重解决方案—重构代码以寻找环境变量。

对于简单的系统, 一个最直接的方案是使用Java的System.getenv()功能从环境中拿到一个或者多个配置信息,或者全部key值和value值的Map. 图 3是代码示例.

图3: 项目依赖POM.xml的一部分

private String userName = System.getenv(“BACKINGSERVICE_UID”);private String password = System.getenv(“BACKINGSERVICE_PASSWORD”);

对于更复杂的系统, Spring Cloud 和 Spring Boot 更流行,它们提供了强大的功能来控制源文件以及解析配置数据.

4.日志

日志应该被视为事件流:一个由应用产生的具有时序性的事件序列。自从使用了云,你就不能使用文件的形式记录日志,你需要将日志输出到stdout/stderr上,供云端提供者,或者相关工具处理。举例说明,Cloud Foundry的loggregator将日志以流的形式输出,以供日志聚合和集中管理。在java中以stdout/stderr的方式记录日志的简单实例如下:

Logger log = Logger.getLogger(MyClass.class.getName());
log.setLevel(Level.ALL);
ConsoleHandler handler = new ConsoleHandler();
handler.setFormatter(new SimpleFormatter());
log.addHandler(handler);
handler.setLevel(Level.ALL);
log.fine(“This is fine.”);

5. 可自由支配

如果你有流程需要一段时间来启动或关闭,那么该流程需要分离一个后台服务并优化提高相应性能.

一个依赖云建立的程序是可自由支配的—它能在任何时间被创建或者销毁。

这种设计有助于确保服务长时间运行良好,并且使你从这种类似于自动扩展的特性中受益。

6.支持服务

一个支持服务是一些你的app依赖的外部事物,例如一个数据库或者一个消息服务器。

app应该以外部配置的方式声明所需的支持服务,例如YAML或者一个跟踪配置服务.

一个云平台处理绑定你的app到相应服务,理想情况下绑定或重新绑定不需要重新启动你的app。

这种松耦合有许多优势,例如允许你使用断路器模式优雅地处理一个强迫停运的情景

7. 环境一致

共同开发和QA沙箱环境,从生产规模和可靠性角度与生产环境比都有不同,但你不能使用一个“雪花”(差距过大,无法正确评估性能)环境!

云平台保持多app环境一致并且可以消除调试环境的差异。

8. 管理琐碎过程

一些你需要管理的程序,例如定时任务,一次性脚步,和其他一些你可能会使用一种编程shell脚本等,来自云平台的支持服务和其他功能,能够帮助你运行这些程序。

目前Java并不像Python或者Ruby以shell方式运行,云平台生态系统有很多选项能够便捷的运行一次性程序或者制作一个shell接口。

9、端口绑定

在无云的世界,典型地看到一些app运行在相同容器,通过端口号来隔离每个app,然后使用DNS来提供一个友好名称来访问。而在云端,你若避开这个微管理——云端提供者将会根据路径与估摸来管理端口分发。

虽然它可能依赖外部机制,为您的app提供流量,但这些机制在容器、机器与平台之间各不同。端口绑定为你提供全量控制,提示你该如何 接收与响应 应用请求,而不管其部署在哪里。

10、进程

这里提及的原始12-因素定义指出app是无状态的。但是,有一些状态需要出现在指定的地方。沿着这些线,这个因素提倡将任何长期运行的状态转换为高速缓存或者数据存储,来实现外部的、逻辑的支撑服务。

11、并发

云平台是沿着横向规模构建的。这些设计如此考虑——你的app应被暴露,处于无状态,并且使用无共享的进程。在平台的进程管理模型中协调工作,重要的是懂得利用特征,比如自动缩放,蓝绿色部署以及其他方面。

12.超出12大要素之外的因素:遥测,安全,API优先设计原则

12大要素的提出大约是在2012年,让我们来看看现代云中的一些基本功能,这些功能会使应用程序的运行更加稳定可靠。

  • 健康 告警, 云系统 指标 , 日志 。

  • 特殊区域 遥测。

  • 应用程序性能检测 (APM)。

在Cloud Foundry上,Java应用程序日志可以简单的的定向到标准输出/标准错误,这里可以通过运算符控制。

Spring Boot使 JMX 更加快捷,而且在商用云平台可以提供像APM这样的先进功能。

应用程序外部的安全,比如应用于使用 RBAC应用程序的 终端(URLs),在云平台为SSO & OAUTH2提供集成显得尤为非重要。否则, 对于多java应用程序的安全性变得难以保障。

Beyond the 12 Factor App 中这样描述将 API优先法则:“是需求优先发展模式的一种扩展,其开发者优先关注于构建应用程序的边缘和接口,随着连续通过CI服务器对集成点的测试,工作团队可以专注各自的服务,仍然保持合理的运行,这是一切正常工作的保证。”

平台革新

总而言之,一个很重要的认识是你不需要仅仅为了满足所有的15条因素而去重新部署一个在云上运行的上线的应用程序,这种 cloud-native 成熟度模型 (由大型金融服务组织表述)说明了被用于处理大型复杂的整体的应用程序和他们“12分解”在逐步发展。

161027、Java 中的 12 大要素及其他因素的更多相关文章

  1. 【多线程与并发】Java中的12个原子操作类

    从JDK1.5开始,Java提供了java.util.concurrent.atomic包,该包中的原子操作类提供了一种使用简单.性能高效(使用CAS操作,无需加锁).线程安全地更新一个变量的方式. ...

  2. java中的12种锁

    java中很多地方会涉及到锁,比如java代码并发场景,DB中的并发场景,分布式中的锁....你知道几种呢?下面来看看常见的11种锁 1. 乐观锁/悲观锁 这两个概念是人们对java中各种锁总结提出的 ...

  3. JVM(二):Java中的语法糖

    JVM(二):Java中的语法糖 上文讲到在语义分析中会对Java中的语法糖进行解糖操作,因此本文就主要讲述一下Java中有哪些语法糖,每个语法糖在解糖过后的原始代码,以及这些语法糖背后的逻辑. 语法 ...

  4. 【Java基础】12、java中方法的参数传递机制

    问:当一个对象被当作参数传递到一个方法后,此方法可改变这个对象的属性,并可返回变化后的结果,那么这里到底是值传递还是引用传递?  答:是值传递.Java 编程语言只有值传递参数.当一个对象实例作为一个 ...

  5. 2017.12.20 Java中的 IO/XML学习总结 File类详细

    IO / XML 一.File类 1.定义/概念 Java是面向对象的语言,要想把数据存到文件中,就必须要有一个对象表示这个文件.File类的作用就是代表一个特定的文件或目录,并提供了若干方法对这些文 ...

  6. 夯实Java基础系列12:深入理解Java中的反射机制

    本系列文章将整理到我在GitHub上的<Java面试指南>仓库,更多精彩内容请到我的仓库里查看 https://github.com/h2pl/Java-Tutorial 喜欢的话麻烦点下 ...

  7. 2019.12.04 Java中的内存分配

    Java内存分配与管理是Java的核心技术之一,之前我们曾介绍过Java的内存管理与内存泄露以及Java垃圾回收方面的知识,今天我们再次深入Java核心,详细介绍一下Java在内存分配方面的知识.一般 ...

  8. 2017.12.25 Java中面向对象思想的深刻理解

    今日内容介绍 1.面向对象思想 2.类与对象的关系 3.局部变量和成员变量的关系 4.封装思想 5.private,this关键字 6.随机点名器 01面向对象和面向过程的思想 * A: 面向过程与面 ...

  9. 第12讲-Java中的IO操作及对象的序列化与反序列化

    1.知识点 1.1.课程回顾 1.2.本章重点 1.2.1  io操作 1.2.2  对象的序列化与反序列化 2.具体内容 2.1.Java IO 2.1.1.什么是IO IO其实就是输入.输出 I ...

随机推荐

  1. SQL-用JOIN连接多个表

    select * from table1 inner join table2 on table1.id=table2.id     其实 INNER JOIN --ON的语法格式可以概括为:      ...

  2. 打造安全的App!iOS安全系列之 HTTPS

    如何打造一个安全的App?这是每一个移动开发者必须面对的问题.在移动App开发领域,开发工程师对于安全方面的考虑普遍比较欠缺,而由于iOS平台的封闭性,遭遇到的安全问题相比于Android来说要少得多 ...

  3. saltstack之基础入门系列文章简介

    使用saltstack已有一段时间,最近由于各种原因,特来整理了saltstack基础入门系列文章,已备后续不断查阅(俗话说好记性不如烂笔头),也算是使用此工具的一个总结.saltstack的前六篇文 ...

  4. 2.准备Python编译环境

    2.准备Python编译环境 2.1下载Python2.7.6.tgz.ipython1.2.1.tgz.sqlite-autoconf-3071401.tar.gz 2.2安装Python2.7.6 ...

  5. Android EditText 改变边框颜色

    第一步:为了更好的比较,准备两个一模一样的EditText(当Activity启动时,焦点会在第一个EditText上,如果你不希望这样只需要写一个高度和宽带为0的EditText即可避免,这里就不这 ...

  6. Android:学习AIDL,这一篇文章就够了(下)

    前言 上一篇博文介绍了关于AIDL是什么,为什么我们需要AIDL,AIDL的语法以及如何使用AIDL等方面的知识,这一篇博文将顺着上一篇的思路往下走,接着介绍关于AIDL的一些更加深入的知识.强烈建议 ...

  7. 如何在APICloud平台使用腾讯X5引擎

    目前APICloud与腾讯X5引擎已经达成全方位的深度合作,APICloud在多个产品线深度集成X5引擎,广大APICloud开发者们即日起可通过以下几方面在你的APP中使用X5引擎,享受X5引擎带来 ...

  8. 解决ScrollView嵌套ViewPager出现的滑动冲突问题

    /**       *         解决ScrollView嵌套ViewPager出现的滑动冲突问题       */       public class ScrollView1 extends ...

  9. HBase shell

    进入命令行 ./hbase shell 查看HBase shell帮助 help 查看命令帮助 直接输入命令回撤 创建命名空间 create_namespace 'ns1' 查看命名空间 list_n ...

  10. 设置GPnP profile文件中asm spfile的位置

    登录asmcmd asmcmd> spset <location-绝对路径> 示例: ASMCMD> spset +DATA/asm/asmparameterfile/asms ...