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