Java雲原生崛起微服務架構Quarkus入門實踐

2022-10-19 06:01:18

@

概述

定義

Quarkus 官網地址 https://quarkus.io/

Quarkus 官網檔案 https://hbase.apache.org/book.html

Quarkus GitHub原始碼地址 https://github.com/quarkusio/quarkus

Quarkus定位要做超聲速、亞原子的Java框架,使用最好標準為OpenJDK HotSpot和GraalVM量身客製化的Kubernetes Native Java棧;從一開始就是針對Kubernetes設計的雲原生優化Java應用開發框架;相容主流的框架開發模式如Jpa、Netty、Undertow、Hibernate、JWT、Spring。最新版本為2.13.2

GraalVM簡介

GraalVM是Oracle開發的高效能的多語言執行時JDK,提高Java應用程式的效能,同時消耗更少的資源。GraalVM提供了兩種執行Java應用程式的方法:在HotSpot JVM上使用Graal即時(JIT)編譯器,或者作為預先(AOT)編譯的本機可執行檔案。除了Java,它還提供了JavaScript、Ruby、Python和其他一些流行語言的執行時。GraalVM的多語言功能使得在一個應用程式中混合程式語言成為可能,同時消除了任何外語呼叫成本。目前最新版本為22.2。

  • GraalVM可以建立原生可執行檔案。
  • GraalVM提供的原生映象(native image)功能可以把Java程式碼預先編譯(Ahead-Of-Time,AOT)成獨立的可執行檔案。該可執行檔案包括了應用本身的程式碼、所依賴的第三方庫和 JDK 本身。該執行檔案並不執行在Java虛擬機器器之上,而是名為Substrate的虛擬機器器。與執行在傳統的Java虛擬機器器上相比,原生可執行檔案在執行時的啟動速度更快,所耗費的記憶體資源更少。可執行檔案的體積也更小。
  • GraalVM生成的原生可執行檔案與底層平臺相關,不能在當前平臺之外的其他平臺上執行。但對雲原生應用來說,這並不是一個問題。雲原生應用的設計目標是在容器中執行,所執行的底層平臺是固定的。

為何使用

相信使用SpringBoot的快速開發企業級應用微服務啟動慢,從一個應用從啟動到服務可用,一般是數秒,在對CPU核數和記憶體嚴格限制的情況下,花數十秒啟動的情況也屢見不鮮,這樣的問題無法適應需要快速重啟或快速擴容的場景;而且記憶體消耗也很大如記憶體,如果限制在1G時FullGC頻率變大,且經常觸發OMM後Kill導致pod重啟,並且啟動時間也會變長,而相比之下,叢集中使用go語言開發的應用則設定128M記憶體也可正常使用。以JVM模式執行的Java應用,並不太適合於雲原生應用的開發,而擁抱雲原生則是未來技術的大趨勢。

  • 容器雲已經為未來主流,也即是軟體都是執行在k8s這樣的容器叢集裡。而容器環境需要應用具備啟動速度快,資源佔用小,響應時間短等特性。Quarkus順應這種趨勢而生的。
    • 對於雲原生應用來說,平臺無關性變得無關緊要。雲原生應用都是以容器化的形式執行的,所執行的底層平臺是固定的。
    • 雲原生應用對啟動速度的要求比較高。當需要進行水平擴充套件時,要求這些新的範例必須在足夠短的時間內完成啟動,從而儘快的處理新增的請求。
    • 雲原生應用要求在執行時佔用儘可能少的資源。儘可能的減少單個範例佔用的資源,就意味著可以用同樣的成本,支援更多的存取請求。
    • 雲原生應用要求更小的打包體積。雲原生應用以容器映象的形式打包。應用映象的尺寸越大,所需要的儲存空間也會越大,推播和拉取映象所耗費的時間也會更長。
  • Quarkus具備企業級應用開發能力。
  • 在Serverless伺服器架構、微服務、容器、Kubernetes、功能即服務(FaaS)和雲環境中執行 Java 而言,考慮了所有這些因素的Quarkus 堪稱是一個有效的解決方案。

特性

  • 容器優先:構建期即生成雲原生映象執行檔案;Quarkus為GraalVM和HotSpot客製化應用程式。快速啟動、低記憶體消耗、體積小,在Kubernetes這樣的容器編排平臺上提供了近乎實時的擴充套件和高密度的記憶體利用率。這就是使用了編譯時引導的技術。

    • 支援 Graal/SubstrateVM。
    • 構建時後設資料處理。
    • 儘量減少JNI呼叫。
    • 減少反射的使用。
    • 本機映像預啟動。
  • Kubernete原生:構建期即生成雲原生映象執行檔案,可以與docker和kubernetes輕鬆整合,Quarkus和Kubernetes的組合可以伸縮、快速建立輕量級的應用程式。Quarkus通過工具、預構建的整合、應用程式服務等顯著提高了開發人員的工作效率。

  • 命令式和響應式:在設計上Quarkus 能夠在開發應用時無縫地結合熟悉的命令式程式碼和非阻塞、響應式樣式。 這對於習慣使用命令式模型而不想切換風格的 Java 開發人員以及使用雲原生/響應式方法的開發人員都非常有用。

  • 社群和標準:擁抱JavaEE標準,使用JavaEE官方Restful、CDI等標準介面。Quarkus提供了一個內聚的、輕量的全棧框架,包含超過50個使用的最佳類庫。。

  • 對開發者友好:學習成本也低,具有統一的設定和簡單的本地可執行檔案生成,零設定,實時重新載入,80%的常用標準和20%靈活應用。

官方效能

從圖中可以看出,使用Quarkus和 GraalVM的簡單的REST應用的啟動時間僅為16毫秒,佔用記憶體僅12MB。如果使用傳統的基於Java虛擬機器器實現,應用的啟動時間需要4.3秒,佔用記憶體為136MB。

實戰

入門範例

步驟

  • 安裝GraalVM
  • 建立quarkus工程
  • IDE匯入專案
  • Idea編碼執行和偵錯
  • 打包成普通的jar
  • 打包成依賴GraalVM的二進位制檔案
  • 打包成不依賴GraalVM的二進位制檔案
  • 製作成Docker映象

安裝GraalVM

瞭解GraalVM的最新版本22.2的使用可以查閱GraalVM官方檔案https://www.graalvm.org/22.2/docs/ ,先從GitHub下載GraalVM,https://github.com/graalvm/graalvm-ce-builds/releases ,這裡先以下載windows版本為例,下載後的檔案graalvm-ce-java11-windows-amd64-22.2.0.zip,解壓到本地磁碟目錄,檢視版本資訊如下

# windows
PATH環境變數增加路徑:D:\Program Files\Java\graalvm-ce-java11-22.2.0\bin
JAVA_HOME設定環境變數:D:\Program Files\Java\graalvm-ce-java11-22.2.0

# linux
wget https://github.com/graalvm/graalvm-ce-builds/releases/download/vm-22.2.0/graalvm-ce-java17-linux-amd64-22.2.0.tar.gz
tar -xvf graalvm-ce-java17-linux-amd64-22.2.0.tar.gz

export GRAALVM_HOME=/home/commons/graalvm-ce-java17-22.2.0
export PATH=$PATH:$GRAALVM_HOME/bin
export JAVA_HOME=${GRAALVM_HOME}
export PATH=$PATH:$JAVA_HOME/bin
export MAVEN_HOME=/home/commons/apache-maven-3.8.6
export PATH=$PATH:$MAVEN_HOME/bin

建立quarkus工程

萬丈高樓平地起,首先是建立quarkus專案,與SpringBoot類似,Quarkus為我們提供了多種方式建立quarkus工程,下面介紹3種:

  • IDEA支援建立quarkus專案

  • maven命令支援建立(使用的是apache-maven-3.8.6)
mvn io.quarkus:quarkus-maven-plugin:create -DprojectGroupId=cn.itxs -DprojectArtifactId=quarkus-web-demo-m -DprojectVersion=1.0-SNAPSHOT -DclassName=FirstResource -Dpath=actions

我們先以第三種為例說明,通過線上網頁生成quarkus-web-demo.zip,解壓後用tree命令看看專案結構,是一個標準的maven工程,多了個docker目錄,裡面有幾個Dockerfile檔案相關的問題,目錄結構如下:

Idea匯入專案

Idea匯入上面的Maven專案,幾分鐘下載依賴後專案已成功匯入,可以看到quarkus專案的pom檔案核心依賴為quarkus-bom,quarkus官方認為傳統的介面就是一個個對外方法的資源所以在quarkus裡面是以Resource資源的概念來進行的。

Idea執行和偵錯

在Idea要執行和偵錯quarkus的專案,首先得在專案新增SDK,並將路徑指向剛才解壓的目錄

修改專案的GreetingResource原始檔範例方法返回值內容"Hello ITXS RESTEasy",同樣也修改單元測試GreetingResourceTest的測試方法的值為上面的內容,在執行選單中點選新增新的Quarkus設定

新建後點選執行按鈕(mvn compile quarkus:dev ),正常執行輸出紀錄檔如下

存取本地http://localhost:8080/hello 後可以看到正確的返回結果,同樣也可以直接點選偵錯按鈕進入偵錯模式

打包成普通的Jar

通過maven的package打包後,生成打包目錄如下

可以直接通過java -jar執行quarkus-app目錄下quarkus-run.jar和quarkus-web-demo-1.0.0-SNAPSHOT-native-image-source-jar目錄下的quarkus-web-demo-1.0.0-SNAPSHOT-runner.jar,不到1秒的時間就啟動完畢了,存取上面測試地址同樣可以看到正確的結果

打包成依賴GraalVM二進位制檔案

此方法打包的二進位制檔案仍需要依賴graalvm,但程式碼已經做了靜態編譯處理,所以執行效率有大幅提升,比較適合容器化啟動。

先安裝vs c++依賴,下載Visual Studio Installer,需要取消中文並選擇英文。然後使用power shell進入到專案根目錄,執行mvn package -Pnative命令後報錯

根據提示安裝native-image執行安裝命令和確認 是否設定了GRAALVM_HOME、JAVA_HOME環境變數

gu install native-image
# 重新執行打包
mvn package -Pnative

直接執行生成的可執行檔案quarkus-web-demo-1.0.0-SNAPSHOT-runner,確實飛快,啟動時間只要0.033s,存取hello也正常顯示。

打包成不依賴GraalVM的二進位制檔案

需要本機先裝有docker的環境,這裡用的是docker desktop,有多種方法,可以直接maven引數構建,也可以在appllications.properties檔案中增加構建引數

quarkus.native.container-build=true
quarkus.native.native-image-xmx=4096m

# 終端命令中執行打包
mvn clean package -Dnative

製作docker映象

直接通過Dockerfile.native製作成docker映象

docker build \
-f src/main/docker/Dockerfile.native \
-t bolingcavalry/quarkus-web-demo:0.0.1 .

執行docker命令成功生成

檢視映象已經生成

通過docker run命令啟動後檢視容器的資訊

通過curl -L http://172.17.0.2:8080/hello -w '\n' 存取頁面也是正常的

**本人部落格網站 **IT小神 www.itxiaoshen.com