Capsule:開源的 JVM 應用部署工具

OneAPM官方技術部落格發表於2015-09-23

【編者按】本文作者 Ron Pressler 是 Parallel Universe 公司的創始人,擁有著豐富的高效能開發經驗。通過這篇文章,Ron 向大家詳細介紹了全新的開源 JVM 部署工具——Capsule, 本文系 OneAPM 工程師編譯整理。

現實世界中,應用程式部署過程可能沒有想象中的那麼簡單。應用程式其實非常「敏感」,在部署過程中,它會發現自己身處一個陌生的環境中,並且在與不同硬體、不同基礎設施軟體,以及陌生的鄰居(應用程式)行互動。如果期望應用程式正常地執行,編碼和部署過程都是重中之重。兩者之間的平衡常常依賴於程式的編寫語言、程式構成的執行時和工具,因此,不同的技術棧可能需要不同的部署工具。

但 JVM 應用程式對環境的要求非常少——只需一個 JVM 和一個核心,然而意想不到是,目前為止尚不存在一個通用的 JVM 應用部署工具/機制。Fat JARs 並不總奏效,而且它們需要平臺特定的指令碼。最近有人使用 Docker 來部署 Java 應用,事實上 Docker 並不適用於這種任務:它的主要目的之一是提供通用的應用可移植性(類似 JVM 應用已經具備的特性),同時它也需要下載、部署並管理各種 full-OS 映象和存 repositories。作為執行時不可知工具,Docker 也無法利用 JVMs 的優勢。

當下,經過一年的發展,Capsule 1.0 正式釋出——一個簡單、健壯且靈活的 JVM 應用部署工具。Capsule 迎合 JVM 應用的獨特優勢和需求,因此這裡有理由相信這是最簡單、最強大的 JVM 應用部署方式,不管是用於一個桌面應用、microservice 或複雜的 Web 應用。Capsule 不僅適用於 Java 應用程式,還能應用於所有 JVM 語言,從 Jruby、Jython 和 Groovy,到 Kotlin、Clojure 和 Scala,再到 Frege 和 OCaml-Java。如果你在寫 JVM 程式,給 Capsule 一個機會。

你可以這樣來理解 capsule,將它當作 steroids 上的1個 fat JAR(在允許本地庫的同時也不會干擾到依賴項)與1個宣告式啟動指令碼的整合;另一個理解方式是,將其當作部署階段的構建工具。正如構建管理工具一樣, Capsule 從構建到應用釋出的各個環節都有全方位的管理。

Capsule 在設計時一直遵循以下原則:

  • 打包應該是輕量、可移植和便捷的。無論多麼複雜,不管有多少 JAR 檔案組成,或者有多少指令碼語言的原始檔還是本地庫,Capsule 都可以包裝任何 JVM 應用到一個名為 Capsule 的可執行 JAR,並且可以在任何平臺上執行。Capsule 可以直接包含應用的所有依賴項,或簡單地宣告部分或者全部,一旦釋出將會被完整的下載。這就是 fat JAR 的工作方式。如果願意, capsules 本身也可以置於 Maven repositories,在釋出時進行下載。

  • 安裝對主機系統的影響最小,並對更新選擇性支援。在 capsule 首次安裝時,其正常執行需要依賴在1個臨時目錄中生成的一些檔案,隨後使用者可以在任何時刻刪除這些檔案,不會對 capsule 產生任何不良影響。capsule 可以選擇性地支援更新——不管是應用或者是其依賴關係——當啟動時會自動下載。這些依賴關係——可以是語言執行時或者是 Web 容器——也可以被其他 capsule 共享。

  • 釋出必須是確定和靈活的,可能是安全的且有選擇地限制。釋出一個 capsule 不需要啟動指令碼。Capsules 查詢請求的 JVM 版本、設定 classpath、必要的 agents 並設定 JVM flags。Capsules 在啟動時也可以建立自己的容器(來限制資源使用,或使用已知的埠以避免對其他專案形成干擾),同時 JVM 應用可以在無特權的容器下執行,這些容器是安全的。另外,安全性由 JVM 提供的安全機制保證。此外, capsules 只需要一個核心和一個 JVM ——甚至不需要 shell,他們便能在 JVM microkernels 上執行,比如 OSv。通過 caplets 和元件定製 capsule 的行為,所有這些功能都是完全可程式設計、可組合的。

當工具和標準已經存在時,不用再重造車輪。Capsule 是用 Java 編寫的,並可以通過 Java 擴充套件。它遵循 JVM 生態系統,而不是重造車輪,僅使用現有的工具和標準。capsule 打包在一個可執行 JAR,並將所有後設資料儲存為簡單的 JAR-manifest attributes 中;並且可以根據需要,從 Maven repositories 中下載全部或者部分,並通過 Maven、Gradle 和 Leiningen 這些流行的 JVM 工具構建。Capsule 本身是一個簡單的 Maven 依賴,就像所有的構建工具外掛,不需要再安裝其他新工具。

通過 Caplets 實現的 Capsule 魔法

Capsule 之所以能保持簡單還能提供這些功能主要歸功於 caplets,以模組化定製 Capsule 行為。Caplets 可以嵌入到1個 capsule,或者單獨進行包裝並使用命令列包裝和修改現有 capsule 行為。

Capsule 的第一個 caplet 是 Maven caplet,允許開發者在 manifest attributes 中宣告部分或全部的應用依賴關係,而不用嵌入到 capsule JAR 裡。雖然這對許多應用來說並不必要,不妨通過以下兩個用例來深入瞭解 Capsule 的潛力。

首先是一個簡單的 Hello World servlet。建成後,它將建立一個標準的 WAR 檔案並部署到任何 servlet 容器。仔細觀察後發現,WAR 的確有點特別。其內容是:

    247 META-INF/MANIFEST.MF 
    1124 WEB-INF/classes/co/paralleluniverse/examples/HelloWorldServlet.class 
    653 WEB-INF/web.xml 
    161596 Capsule.class 
    1467463 capsule-maven-1.0.jar

如你所見, WAR 包含 Capsule 類,這意味著它是一個capsule,也是嵌入式 JAR,而 capsule-maven-1.0.jar是 Maven caplet。JAR manifest 是這樣的:

Manifest-Version: 1.0
Main-Class: Capsule
Premain-Class: Capsule
Caplets: co.paralleluniverse:capsule-maven:1.0
Application: org.eclipse.jetty:jetty-runner:9.3.3.v20150827
Allow-Snapshots: true
Min-Java-Version: 1.7.0
Args: $CAPSULE_JAR

取代部署 WAR 到 servlet 容器,你可以直接執行 java -jar build/libs/capsule-runnable-war.war (或者,甚至簡單的./capsule-runnable-war.war,如果 capsule是「真正可執行」——見使用者文件的指令),它會自動下載 Jetty,並用 Jetty 來啟動 servlet。Jetty 工件將被快取,並可以共享到其他需要的 caplets中。

另一個例子使用 JavaScript,Avatar 專案在 JVM 上實現 Node.js。capsule JAR 包含了 JavaScript 源、 Capsule 類和 Maven caplet:

    608 META-INF/MANIFEST.MF
    161596 Capsule.class
    1467463 capsule-maven-1.0.jar
    266 app.js

當 capsule 釋出,Avatar 執行時——包括針對本地作業系統的本地庫,將從 Maven repository 下載到本地並快取,並與其他 Avatar capsules 共享。

其他 caplets 將包含:一個守護程式 caplet, 作為 Unix 或 Windows 守護程式來發布 capsule;一個安全 caplet,會在 Java 沙箱(通過安全策略定義)內啟動 capsule;一個 desktop caplet,會將包含了一個 GUI 應用程式的 capsule 轉化為一個 Windows、Mac 或 Linux 的本地可執行程式;一個容器 caplet,在一個或多個容器內執行 capsule。

為 Capsules 設計的輕量級容器

容器對沙箱應用來說是一個有效方式,可以簡化部署和鞏固伺服器,所以對任何的軟體堆疊而言,它們都非常有利於 dev-ops 和安全。然而,由於 JVM 應用只有最小的環境需求 (即一個核心和一個 JVM),它們通常是可移植的,使用一個像 Docker 的容器解決方案無疑是浪費時間和空間。另一方面,shield caplet 建立了一個輕量級容器,無需建立大影像。

例如,可以通過簡單地橋接網路在1個容器中方便地執行 quasar-stocks Web 應用。

java -jar capsule-shield-0.1.0.jar quasar-stocks-thin.jar

隨後就可以輕鬆地檢索程式所執行的容器IP地址:

lxc-attach -P ~/.capsule/apps/quasarstocks.Application_0.1.0-SNAPSHOT/capsule-shield/ -n lxc -- /sbin/ifconfig

當一切如預期那樣正常工作,無需任何複雜的操作,就可以在最終部署的伺服器上(可能是一個守護程式)釋出相同的命令來配置埠轉發使服務公共可用,並通過沙箱保證了應用程式的強安全性。

現在

是時間開啟 capsule.io 並啟動 capsules 了!

  1. 它們需要跟蹤以避免衝突,甚至這樣還不夠,因為它們不支援本地庫。
  2. 它們可能需要不可移植的釋出指令碼,以便於在作業系統 shell 命令下執行,並選擇正確的 JRE 版本、設定類路徑、代理和 JVM 引數。
  3. 所有平臺都支援 JVM,必要的指令碼和本地構件可能也一樣需要。
  4. 可能需要更長的啟動時間,比如依賴項需要重新下載。
  5. shield caplet 使用 LXC 將 capsule 放於容器內。

原文連結:https://dzone.com/articles/open-source-jvm-application-deployment-tool-capsul-1

OneAPM for Java 能夠深入到所有 Java 應用內部完成應用效能管理和監控,包括程式碼級別效能問題的可見性、效能瓶頸的快速識別與追溯、真實使用者體驗監控、伺服器監控和端到端的應用效能管理。想閱讀更多技術文章,請訪問 OneAPM 官方部落格

相關文章