Java 中的 12 大要素及其他因素

zuiyfqrat 8年前發布 | 7K 次閱讀 Java Java開發

對于許多人來說,“原生云”和“應用程序的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分解”在逐步發展。

 

來自:https://www.oschina.net/translate/12-factors-and-beyond-in-java

 

 本文由用戶 zuiyfqrat 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!