導讀:在 Kube.NETes 中運行無服務器函數時,實現更快的啟動速度和更小的內存占用。
本文字數:5814,閱讀時長大約: 7分鐘
由于運行上千個應用程序容器莢(Pod)所耗費的資源多,令它實現較少工作節點和資源占用所需成本也較高,所以在使用 opensource.com 時,快速啟動和較少的內存占用是至關重要的。在 Kubernetes 平臺運行容器化微服務時,內存占用是比吞吐量更重要的考量因素,這是因為:
? 由于需要持續運行,所以耗費資源更多(不同于 CPU 占用)
? 微服務令開銷成本成倍增加
? 一個單體應用程序變為若干個微服務的情況(例如 20 個微服務占用的存儲空間約有 20GB)
這些情況極大影響了無服務器函數的發展和 JAVA 部署模型。到目前為止,許多企業開發人員選擇 Go、Python/ target=_blank class=infotextkey>Python 或 Node.js 這些替代方案來解決性能瓶頸,直到出現了 quarkus.io 這種基于 kubernetes 的原生 Java 堆棧,才有所改觀。本文介紹如何在使用了 Quarkus 的 kubernetes 平臺上進行性能優化,以便運行無服務器函數。
容器優先的設計理念
由于 Java 生態系統中傳統的框架都要進行框架的初始化,包括配置文件的處理、classpath
的掃描、類加載、注解的處理以及構建元模型,這些過程都是必不可少的,所以它們都比較耗費資源。如果使用了幾種不同的框架,所耗費的資源也是成倍增加。
Quarkus 通過“左移(shifting left)”,把所有的資源開銷大的操作都轉移到構建階段,解決了這些 Java 性能問題。在構建階段進行代碼和框架分析、字節碼轉換和動態元模型生成,而且只有一次,結果是:運行時可執行文件經過高度優化,啟動非常快,不需要經過那些傳統的啟動過程,全過程只在構建階段執行一次。
Quarkus Build phase
更重要的是:Quarkus 支持構建原生可執行文件,它具有良好性能,包括快速啟動和極小的駐留集大小(resident set size)(RSS)內存占用,跟傳統的云原生 Java 棧相比,具備即時擴展的能力和高密度的內存利用。
Quarkus RSS and Boot Time Metrics
這里有個例子,展示如何使用 Quarkus 將一個 opensource.com 項目構建為本地可執行文件。
1、使用 Quarkus 創建無服務器 Maven 項目
以下命令生成一個 Quarkus 項目,(例如quarkus-serverless-native
)以此創建一個簡單的函數:
-
$ mvn io.quarkus:quarkus-maven-plugin:1.13.4.Final:create
-
-DprojectGroupId=org.acme
-
-DprojectArtifactId=quarkus-serverless-native
-
-DclassName="org.acme.getting.started.GreetingResource"
2、構建一個本地可執行文件
你需要使用 GraalVM 為 Java 程序構建一個本地可執行文件。你可以選擇 GraalVM 的任何發行版,例如 www.graalvm.org 或 github.com(Oracle GraalVM CE 的下游發行版)。Mandrel 是為支持 OpenJDK 11 上的 Quarkus-native 可執行文件的構建而設計的。
打開pom.xml
,你將發現其中的native
設置。你將使用它來構建本地可執行文件。
-
native
-
native
注意: 你可以在本地安裝 GraalVM 或 Mandrel 發行版。你也可以下載 Mandrel 容器映像來構建它(像我那樣),因此你還需要在本地運行一個容器引擎(例如 Docker)。
假設你已經打開了容器運行時,此時需要運行一下 Maven 命令:
使用 www.docker.com 作為容器引擎:
-
$ ./mvnw package -Pnative
-
-Dquarkus.native.container-build=true
-
-Dquarkus.native.container-runtime=docker
使用 podman.io 作為容器引擎:
-
$ ./mvnw package -Pnative
-
-Dquarkus.native.container-build=true
-
-Dquarkus.native.container-runtime=podman
輸出信息結尾應當是BUILD SUCCESS
。
Native Build Logs
不借助 JVM 直接運行本地可執行文件:
-
$ target/quarkus-serverless-native-1.0.0-SNAPSHOT-runner
輸出信息類似于:
-
__ ____ __ _____ ___ __ ____ ______
-
--/ __ / / / / _ | / _ / //_/ / / / __/
-
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /
-
--________/_/ |_/_/|_/_/|_|____/___/
-
INFO [io.quarkus] (main) quarkus-serverless-native 1.0.0-SNAPSHOT native
-
(powered by Quarkus xx.xx.xx.) Started in 0.019s. Listening on: http://0.0.0.0:8080
-
INFO [io.quarkus] (main) Profile prod activated.
-
INFO [io.quarkus] (main) Installed features: [cdi, kubernetes, resteasy]
簡直是超音速!啟動只花了 19 毫秒。你的運行時間可能稍有不同。
使用 linux 的ps
工具檢測一下,結果內存占用還是很低。檢測的方法是:在應用程序運行期間,另外打開一個終端,運行如下命令:
-
$ ps -o pid,rss,command -p $(pgrep -f runner)
輸出結果類似于:
-
PID RSS COMMAND
-
10246 11360 target/quarkus-serverless-native-1.0.0-SNAPSHOT-runner
該進程只占 11MB 內存。非常小!
注意: 各種應用程序(包括 Quarkus)的駐留集大小和內存占用,都因運行環境而異,并隨著應用程序載入而上升。
你也可以使用 REST API 訪問這個函數。輸出結果應該是Hello RESTEasy
:
-
$ curl localhost:8080/hello
-
Hello RESTEasy
3、把函數部署到 Knative 服務
如果你還沒有創建命名空間,現在就在 docs.okd.io(OpenShift Kubernetes 發行版) docs.okd.io(例如quarkus-serverless-native
),進而把這個本地可執行文件部署為無服務器函數。然后添加quarkus-openshift
擴展:
-
$ ./mvnw -q quarkus:add-extension -Dextensions="openshift"
向src/main/resources/Application.properties
文件中添加以下內容,配置 Knative 和 Kubernetes 的相關資源:
-
quarkus.container-image.group=quarkus-serverless-native
-
quarkus.container-image.registry=image-registry.openshift-image-registry.svc:5000
-
quarkus.native.container-build=true
-
quarkus.kubernetes-client.trust-certs=true
-
quarkus.kubernetes.deployment-target=knative
-
quarkus.kubernetes.deploy=true
-
quarkus.openshift.build-strategy=docker
構建本地可執行文件,并把它直接部署到 OKD 集群:
-
$ ./mvnw clean package -Pnative
注意: 提前使用 oc login 命令,確保登錄的是正確的項目(例如 quarkus-serverless-native)。
輸出信息結尾應當是BUILD SUCCESS
。完成一個本地二進制文件的構建并部署為 Knative 服務需要花費幾分鐘。成功創建服務后,使用kubectl
或oc
命令工具,可以查看 Knative 服務和版本信息:
-
$ kubectl get ksvc
-
NAME URL [...]
-
quarkus-serverless-native http://quarkus-serverless-native-[...].SUBDOMAIN True
-
$ kubectl get rev
-
NAME CONFIG NAME K8S SERVICE NAME GENERATION READY REASON
-
quarkus-serverless-native-00001 quarkus-serverless-native quarkus-serverless-native-00001 1 True
4、訪問本地可執行函數
運行kubectl
命令,搜索無服務器函數的節點:
-
$ kubectl get rt/quarkus-serverless-native
輸出信息類似于:
-
NAME URL READY REASON
-
quarkus-serverless-native http://quarkus-serverless-restapi-quarkus-serverless-native.SUBDOMAIN True
用curl
命令訪問上述信息中的URL
字段:
-
$ curl http://quarkus-serverless-restapi-quarkus-serverless-native.SUBDOMAIN/hello
過了不超過一秒鐘,你也會得到跟本地操作一樣的結果:
-
Hello RESTEasy
當你在 OKD 群集中訪問 Quarkus 運行中的節點的日志,你會發現本地可執行文件正在以 Knative 服務的形式運行。
Native Quarkus Log
下一步呢?
你可以借助 GraalVM 發行版優化 Java 無服務器函數,從而在 Knative 中使用 Kubernetes 將它們部署為無服務器函數。Quarkus 支持在普通的微服務中使用簡易配置進行性能優化。
本系列的下一篇文章將指導你在不更改代碼的情況下跨多個無服務器平臺實現可移植函數。
(Daniel Oh, creativecommons.org)
via:
作者: 選題: 譯者: 校對:
本文由 原創編譯, 榮譽推出
LCTT 譯者 :cool-summer-021
翻譯: 4.0 篇
貢獻: 33 天
2022-09-22
2022-10-24
https://linux.cn/lctt/cool-summer-021
歡迎遵照 CC-BY-SA 協議規定轉載,
如需轉載,請在文章下留言 “ 轉載:公眾號名稱”,
我們將為您添加白名單,授權“ 轉載文章時可以修改”。