在 Kubernetes 中優(yōu)化 Java 的 Serverless 功能

實(shí)現(xiàn)更快的啟動(dòng)和更小的內(nèi)存占用,以在 Kubernetes 上運(yùn)行 serverless 功能。
由于運(yùn)行數(shù)千個(gè)應(yīng)用程序 pod 的費(fèi)用以及使用更少的工作節(jié)點(diǎn)和其他資源來(lái)節(jié)省成本,在 Kubernetes 中更快的啟動(dòng)和更小的內(nèi)存占用總是很重要的。 在 Kubernetes 上的容器化微服務(wù)上,內(nèi)存比吞吐量更重要,因?yàn)椋?/span>
- 由于永久性(與 CPU 周期不同),它更昂貴。
- 微服務(wù)成倍增加開(kāi)銷(xiāo)成本。
- 一個(gè)單體應(yīng)用變成 N 個(gè)微服務(wù)(例如,20 個(gè)微服務(wù) ≈ 20GB)
這會(huì)顯著影響 serverless 功能開(kāi)發(fā)和 Java 部署模型。 這是因?yàn)樵S多企業(yè)開(kāi)發(fā)人員選擇了 Go、Python 和 Nodejs 等替代方案來(lái)克服性能瓶頸——直到現(xiàn)在,感謝 Quarkus,一個(gè)新的 Kubernetes 原生 Java 堆棧。 本文介紹了如何優(yōu)化 Java 性能以使用 Quarkus 在 Kubernetes 上運(yùn)行 serverless 功能。
容器優(yōu)先設(shè)計(jì)
Java 生態(tài)系統(tǒng)中的傳統(tǒng)框架在初始化這些框架所需的內(nèi)存和啟動(dòng)時(shí)間方面是有代價(jià)的,包括配置處理、類(lèi)路徑掃描、類(lèi)加載、注釋處理和構(gòu)建世界的元模型,框架需要這些操作。對(duì)于不同的框架,這一次又一次地成倍增加。
Quarkus 通過(guò)將幾乎所有開(kāi)銷(xiāo)“左移”到構(gòu)建階段來(lái)幫助解決這些 Java 性能問(wèn)題。通過(guò)在構(gòu)建時(shí)只進(jìn)行一次代碼和框架分析、字節(jié)碼轉(zhuǎn)換和動(dòng)態(tài)元模型生成,您最終會(huì)得到一個(gè)高度優(yōu)化的運(yùn)行時(shí)可執(zhí)行文件,它啟動(dòng)速度超快,并且不需要傳統(tǒng)啟動(dòng)的所有內(nèi)存,因?yàn)楣ぷ髟跇?gòu)建階段完成一次。

更重要的是,Quarkus 允許您構(gòu)建具有性能優(yōu)勢(shì)的本機(jī)可執(zhí)行文件,包括驚人的快速啟動(dòng)時(shí)間和非常小的駐留集大小 (RSS) 內(nèi)存,與傳統(tǒng)云相比,可實(shí)現(xiàn)即時(shí)擴(kuò)展和高密度內(nèi)存利用率—— 本機(jī) Java 堆棧。

這是一個(gè)快速示例,說(shuō)明如何使用 Quarkus 通過(guò) Java serverless 功能項(xiàng)目構(gòu)建本機(jī)可執(zhí)行文件。
一、創(chuàng)建 Quarkus serverless Maven 項(xiàng)目
這個(gè)命令會(huì)生成一個(gè) Quarkus 項(xiàng)目(例如 quarkus-serverless-native)來(lái)創(chuàng)建一個(gè)簡(jiǎn)單的函數(shù):

二、構(gòu)建原生可執(zhí)行文件
您需要一個(gè) GraalVM 來(lái)為 Java 應(yīng)用程序構(gòu)建本機(jī)可執(zhí)行文件。 您可以選擇任何 GraalVM 發(fā)行版,例如 Oracle GraalVM 社區(qū)版 (CE) 和 Mandrel(Oracle GraalVM CE 的下游發(fā)行版)。 Mandrel 旨在支持在 OpenJDK 11 上構(gòu)建 Quarkus 原生可執(zhí)行文件。
打開(kāi) pom.xml,你會(huì)發(fā)現(xiàn)這個(gè)原生配置文件。 您將使用它來(lái)構(gòu)建本機(jī)可執(zhí)行文件:

注意:您可以在本地安裝 GraalVM 或 Mandrel 發(fā)行版。 您還可以下載 Mandrel 容器鏡像來(lái)構(gòu)建它(就像我所做的那樣),因此您需要在本地運(yùn)行容器引擎(例如 Docker)。
假設(shè)您已經(jīng)啟動(dòng)了容器運(yùn)行時(shí),請(qǐng)運(yùn)行以下 Maven 命令之一。
對(duì)于 Docker:

對(duì)于 Podman:

輸出應(yīng)以 BUILD SUCCESS 結(jié)束。

在沒(méi)有 Java 虛擬機(jī) (JVM) 的情況下直接運(yùn)行本機(jī)可執(zhí)行文件:

輸出將如下所示:

超音速! 啟動(dòng)時(shí)間為 19 毫秒。 時(shí)間可能因您的環(huán)境而異。
正如 Linux ps 實(shí)用程序報(bào)告的那樣,它還具有極低的內(nèi)存使用率。 在應(yīng)用程序運(yùn)行時(shí),在另一個(gè)終端中運(yùn)行此命令:

你應(yīng)該看到類(lèi)似的東西:

此過(guò)程使用大約 11MB 的內(nèi)存 (RSS)。 相當(dāng)緊湊!
注意:任何應(yīng)用程序(包括 Quarkus)的 RSS 和內(nèi)存使用量將根據(jù)您的特定環(huán)境而有所不同,并且會(huì)隨著應(yīng)用程序體驗(yàn)的加載而增加。
您還可以使用 REST API 訪問(wèn)該函數(shù)。 那么輸出應(yīng)該是 Hello RESTEasy:

三、將功能部署到 Knative 服務(wù)
如果您還沒(méi)有,請(qǐng)?jiān)?nbsp;OKD(OpenShift Kubernetes Distribution)上創(chuàng)建一個(gè)命名空間(例如 quarkus-serverless-native),以將此本機(jī)可執(zhí)行文件部署為無(wú)服務(wù)器功能。 然后為 Knative 服務(wù)部署添加一個(gè) quarkus-openshift 擴(kuò)展:

在 src/main/resources/application.properties 中添加以下變量來(lái)配置 Knative 和 Kubernetes 資源:

構(gòu)建本機(jī)可執(zhí)行文件,然后直接將其部署到 OLD 集群:

注意:確保提前使用 oc login 命令登錄到正確的項(xiàng)目(例如 quarkus-serverless-native)。
輸出應(yīng)以 BUILD SUCCESS 結(jié)束。 完成原生二進(jìn)制構(gòu)建并部署新的 Knative 服務(wù)需要幾分鐘時(shí)間。 成功創(chuàng)建服務(wù)后,您應(yīng)該使用 kubectl 或 oc 命令工具看到 Knative 服務(wù) (KSVC) 和修訂版 (REV):

四、訪問(wèn)原生可執(zhí)行函數(shù)
通過(guò)運(yùn)行以下 kubectl 命令檢索 serverless 函數(shù)的端點(diǎn):

輸出應(yīng)如下所示:

使用 curl 命令訪問(wèn)路由 URL:

不到一秒鐘,您將獲得與本地相同的結(jié)果:

當(dāng)您訪問(wèn) OLD 集群中的 Quarkus 運(yùn)行 pods 日志時(shí),您將看到本機(jī)可執(zhí)行文件作為 Knative 服務(wù)運(yùn)行。

下一步是什么?
您可以使用 GraalVM 發(fā)行版優(yōu)化 Java serverless功能,將它們作為無(wú)服務(wù)器功能部署在 Knative 和 Kubernetes 上。 Quarkus 使用普通微服務(wù)中的簡(jiǎn)單配置來(lái)實(shí)現(xiàn)這種性能優(yōu)化。



























