Java 無服務(wù)器函數(shù)入門
對 ??無服務(wù)器 Java?? 的研究始于函數(shù) —— 就是按需求運行的一小段代碼。這一階段并沒有持續(xù)很長時間。雖然在 1.0 階段,基于虛擬機架構(gòu)的函數(shù)使這種范式變得很流行,但它仍然有局限性,例如執(zhí)行時間、協(xié)議和糟糕的本地開發(fā)體驗,都不太理想,如下圖所示。
開發(fā)者隨后意識到,可以把同樣的無服務(wù)器特性應(yīng)用于微服務(wù)和 Linux 容器,帶來的好處也是一樣的。由此進入 1.5 階段,在這個階段,一些無服務(wù)器容器完全抽象化了 ??Kubernetes??,通過 ??Knative?? 或其它位于它之上的抽象層來提供無服務(wù)器的體驗。
在 2.0 階段,無服務(wù)器開始處理更復(fù)雜的編排和集成模式,并結(jié)合某些層級的狀態(tài)管理。更重要的是,開發(fā)者關(guān)注的是能否在舊的系統(tǒng)中使用熟悉的 Java 應(yīng)用程序運行時來組合運行無服務(wù)器和非無服務(wù)器的工作負載。
The serverless Java journey
Java 開發(fā)者開始進行無服務(wù)器函數(shù)開發(fā)之前,第一步是要選擇一種新的云原生 Java 框架,從而能夠以快于傳統(tǒng)單體應(yīng)用程序的速度和較小的內(nèi)存占用運行 Java 函數(shù)。這在各種基礎(chǔ)設(shè)施環(huán)境中,包括物理服務(wù)器、虛擬機、多云或混合云環(huán)境中的容器,都是適用的。
開發(fā)者也有可能固執(zhí)地選擇 Spring 框架中的 ??Spring 云函數(shù)?? 來進行命令式和反應(yīng)式函數(shù)的開發(fā)。Spring 也支持將 Java 函數(shù)部署到可安裝的無服務(wù)器平臺,比如 ??Kubeless??、??Apache OpenWhisk??、??Fission?? 和 ??Project Riff??。然而,人們擔(dān)心 Spring 的啟動慢、響應(yīng)時間長以及內(nèi)存占用大的問題。在諸如 Kubernetes 這種可擴展的容器環(huán)境中運行 Java 函數(shù),這些問題可能會更嚴重。
??Quarkus?? 是一個新推出的開源云原生 Java 框架,它有助于解決這些問題。它的作用是設(shè)計無服務(wù)器應(yīng)用程序,以及編寫運行于云基礎(chǔ)設(shè)施(例如 Kubernetes)的云原生微服務(wù)。
Quarkus 重新審視了 Java,它使用了封閉的方法構(gòu)建和運行 Java 程序。它把 Java 轉(zhuǎn)變?yōu)橐环N可與 Go 相媲美的運行時。Quarkus 也包含 100 多種擴展功能,集成了企業(yè)級能力,例如數(shù)據(jù)庫訪問、無服務(wù)器集成、消息、安全、可觀察性和業(yè)務(wù)自動化。
這里有一個簡單例子,展現(xiàn)如何使用 Quarkus 創(chuàng)建一個 Java 無服務(wù)器項目的框架。
1、基于 Maven 創(chuàng)建一個 Quarkus 無服務(wù)器項目
安裝一個本地 Kubernetes 集群,開發(fā)者有多種選擇,包括 ??Minikube?? 和 ??OKD??。因為使用 OKD 在 Knative 和 DevOps 工具上安裝無服務(wù)器相關(guān)功能較方便,本文使用 OKD 安裝集群。這些關(guān)于 ??OKD 安裝?? 和 ??Knative 操作員安裝?? 的相關(guān)指南中提供了更多的設(shè)置資料。
下面的命令創(chuàng)建了一個 Quarkus 項目(例如 ??quarkus-serverless-restapi?
?),對外暴露一個簡單的 REST API,并下載 ??quarkus-openshift?
? 擴展,用于 Knative 服務(wù)的部署:
$ mvn io.quarkus:quarkus-maven-plugin:1.13.4.Final:create \
-DprojectGroupId=org.acme \
-DprojectArtifactId=quarkus-serverless-restapi \
-Dextensions="openshift" \
-DclassName="org.acme.getting.started.GreetingResource"
2、在本地運行無服務(wù)器功能
使用 Quarkus 開發(fā)模式運行程序,檢查 REST API 是否有效,稍稍調(diào)整一下代碼:
$ ./mvnw quarkus:dev
輸出如下內(nèi)容:
__ ____ __ _____ ___ __ ____ ______
--/ __ \/ / / / _ | / _ \/ //_/ / / / __/
-/ /_/ / /_/ / __ |/ , _/ ,< / /_/ /\ \
--\___\_\____/_/ |_/_/|_/_/|_|\____/___/
INFO [io.quarkus] (Quarkus Main Thread) quarkus-serverless-restapi 1.0.0-SNAPSHOT on JVM (powered by Quarkus xx.xx.xx.) started in 2.386s. Listening on: http://localhost:8080
INFO [io.quarkus] (Quarkus Main Thread) Profile dev activated. Live Coding activated.
INFO [io.quarkus] (Quarkus Main Thread) Installed features: [cdi, kubernetes, resteasy]
注意: 保持 Quarkus 應(yīng)用程序運行,需要使用熱部署Live Coding。這樣,當(dāng)代碼修改后,你就不必重新構(gòu)建、重新部署以及重啟運行時。
現(xiàn)在,你可以使用一個 ??curl?
? 命令快速訪問 REST API。輸出結(jié)果應(yīng)當(dāng)是 ??Hello RESTEasy?
?:
$ curl localhost:8080/hello
Hello RESTEasy
在 ??GreetingResource.java?
? 中修改返回值:
public String hello() {
return "Quarkus Function on Kubernetes";
}
再次訪問 REST API,輸出信息也會相應(yīng)更新:
$ curl localhost:8080/hello
Quarkus Function on Kubernetes
普通的微服務(wù)跟無服務(wù)器函數(shù)之間的差別并不大。使用 Quarkus 的好處在于:開發(fā)者可以使用任何微服務(wù),將 Kubernetes 部署為無服務(wù)器函數(shù)。
3、在 Knative 服務(wù)中部署相關(guān)的函數(shù)
如果你還沒有創(chuàng)建命名空間,就在你的 OKD 集群上 ??創(chuàng)建命名空間??(例如 ??quarkus-serverless-restapi?
?),用來部署 Java 無服務(wù)器函數(shù)。
Quarkus 令開發(fā)者可以通過在 ??src/main/resources/application.properties?
? 中添加以下變量,創(chuàng)建 Knative 和 Kubernetes 資源:
quarkus.container-image.group=quarkus-serverless-restapi <1>
quarkus.container-image.registry=image-registry.openshift-image-registry.svc:5000 <2>
quarkus.kubernetes-client.trust-certs=true <3>
quarkus.kubernetes.deployment-target=knative <4>
quarkus.kubernetes.deploy=true <5>
quarkus.openshift.build-strategy=docker <6>
說明:
- <1> 在你部署無服務(wù)器應(yīng)用程序的位置定義項目名
- <2> 使用容器注冊中心
- <3> 在這個簡單例子中,使用自簽名證書,以便通過相關(guān)信任機制
- <4> 允許創(chuàng)建 Knative 資源
- <5> 指示在構(gòu)建容器映像之后將擴展部署到 OpenShift
- <6> 設(shè)置 Docker 構(gòu)建策略
執(zhí)行以下命令,構(gòu)建應(yīng)用程序,并直接部署到 OKD 集群:
$ ./mvnw clean package -DskipTests
注意: 應(yīng)該提前使用 ?
?oc login?
? 命令,確保登錄到正確的項目(例如??quarkus-serverless-restapi?
?)。
輸出結(jié)果應(yīng)該以 ??BUILD SUCCESS?
? 結(jié)束。
在對于 Knative 服務(wù)執(zhí)行的 ??oc?
? 命令中,加上標簽:
$ oc label rev/quarkus-serverless-restapi-00001
app.openshift.io/runtime=quarkus --overwrite
然后訪問 OKD 網(wǎng)頁控制臺,就能進入 ??開發(fā)人員透視圖中的拓撲視圖??。你可能會看到你的容器莢Pod(無服務(wù)器函數(shù))已經(jīng)縮小為零(白線圈)。
Topology view
4、在 Kubernetes 環(huán)境下測試函數(shù)
運行如下 ??oc?
? 命令,搜索含有無服務(wù)器函數(shù)的路由:
$ oc get rt/quarkus-serverless-restapi
[...]
NAME URL READY REASON
quarkus-serverless[...] http://quarkus[...].SUBDOMAIN True
使用 ??curl?
? 命令訪問搜索到的路由:
$ curl http://quarkus-serverless-restapi-quarkus-serverless-restapi.SUBDOMAIN/hello
過幾秒鐘,你可以得到跟在本地相同的結(jié)果:
Quarkus Function on Kubernetes
當(dāng)你回到 OKD 集群內(nèi)的拓撲圖,Knative 服務(wù)會自動擴展。
Scaling the Knative Function
由于 Knative 服務(wù)的默認設(shè)置,其 pod 在 30 秒后會再次下降至零。
下一步呢?
無服務(wù)器不斷地在演變,始于運行于虛擬機的函數(shù),到后來的無服務(wù)器容器,并與企業(yè)原有系統(tǒng)集成。在此過程中,企業(yè)開發(fā)者借助 Quarkus,仍然可以使用自己熟悉的技術(shù)(比如 Java)創(chuàng)建一個項目,然后構(gòu)建并部署到 Kubernetes。
本系列的下一篇文章將指導(dǎo)你優(yōu)化 Kubernetes 中的 Java 無服務(wù)器函數(shù),從而令程序啟動更快,內(nèi)存占用更小。