支援JDK19虛擬執行緒的web框架,之二:完整開發一個支援虛擬執行緒的quarkus應用

2023-09-14 15:00:43

歡迎存取我的GitHub

這裡分類和彙總了欣宸的全部原創(含配套原始碼):https://github.com/zq2599/blog_demos

本篇概覽

  • 本篇是《支援JDK19虛擬執行緒的web框架》系列的中篇,前文咱們體驗了有虛擬執行緒支援的web服務,經過測試,發現效能上它與其他兩種常見web架構並無明顯區別,既然如此,還有必要研究和學習嗎?
  • 當然有必要,而且還要通過實戰更深入瞭解虛擬執行緒與常規執行緒的區別,在各大框架和庫廣泛支援虛擬執行緒之前,打好理論和實踐基礎,這才是本系列的目標
  • 為了接下來的深入瞭解,咱們先在本篇打好基礎:詳細說明前文的web功能是如何開發出來的
  • 為了突出重點,這裡先提前劇透,從編碼的角度說清楚如何開啟虛擬執行緒支援,其實非常簡單,如下圖,左側是quarkus框架下的一個普通web服務,每收到一個web請求,是由執行緒池中的執行緒負責響應的,右側的web服務多了個@RunOnVirtualThread註解,就變成了由新建的虛擬執行緒去處理web請求,沒錯,在quarkus框架下使用虛擬執行緒就是這麼簡單

  • 在前文中,我們通過返回值也看到了上述兩個web服務中,負責web響應的執行緒的不同,如下所示,從執行緒名稱上很容易看出執行緒池和虛擬執行緒的區別

  • 看到這裡,您可能會說:就這?一個註解就搞定的事情,你還要寫一篇文章?這不是在浪費作者你自己和各位讀者的時間嗎?

  • 確實,開啟虛擬執行緒,編碼只要一行,然而就目前而言,虛擬執行緒是JDK19專屬,而且還只是預覽功能,要想在實際執行的時候真正開啟並不容易,需要從JDK、maven、IDE等方方面面都要做相關設定,而且如果要做成前文那樣的docker映象,一行docker run命令就能開啟虛擬執行緒,還要在Dockerfile上做點事情(quarkus提供的基礎映象中沒有JDK19版本,另外啟動命令也要調整)

  • 上述這些都是本文的重點,欣宸已經將這些梳理清楚了,接下來咱們一起實戰吧,讓前文體驗過的web從無到有,再到順利執行,達到預期

  • 整個開發過程如下圖所示,一共十步,接下來開始動手

  • 修改後令環境變數生效,然後執行一下命令確認已經使用了JDK19
➜  ~ mvn -version
Apache Maven 3.8.5 (3599d3414f046de2324203b78ddcf9b5e4388aa0)
Maven home: /Users/zhaoqin/software/apache-maven-3.8.5
Java version: 19, vendor: Azul Systems, Inc., runtime: /Library/Java/JavaVirtualMachines/zulu-19.jdk/Contents/Home
Default locale: zh_CN_#Hans, platform encoding: UTF-8
OS name: "mac os x", version: "12.6", arch: "aarch64", family: "mac"

建立Quarkus專案

  • 開啟IDEA,新建專案,選擇Quarkus專案

  • 其次是Modules設定,先設定Sources這個tab頁

  • 接下來是Dependencies這個tab頁

  • 選中Add VM options
image-20221015115859652
  • 填入下圖箭頭所指的內容
image-20221015120024775
  • 終於,設定完成,接下來要啟動應用了

啟動和驗證

  • 啟動應用之前,請確認postgresql資料庫已啟動,並且資料已經匯入,具體啟動和匯入方法請參考前文
  • 點選下圖紅色箭頭中指向的按鈕,即可在IDEA中執行應用
image-20221021081112061 image-20221021082603972
  • 在前文中,咱們是在docker上執行應用的,另外在實際場景中應用執行在docker或者k8s環境也是普遍情況,所以接下來一起實戰將用做成docker映象並驗證

構建映象

  • 在建立工程的時候,IDEA就用quarkus模板自動建立了多個Dockerfile檔案,下圖紅框中全是
image-20221021083348600
  • 如果當前應用的JDK不是19,而是11或者17,那麼上圖紅框中的Dockerfile檔案就能直接使用了,然而,由於今天咱們應用的JDK必須是19,就無法使用這些Dockerfile了,必須自己寫一個,原因很簡單,開啟Dockerfile.jvm,如下圖紅色箭頭所示,基礎映象是jdk17,而這個倉庫中並沒有JDK19,也就是說quarkus還沒有釋出JDK19版本的基礎映象,咱們要自己找一個,另外,容器啟動命令也要調整,需要加入--enable-preview才能開啟JVM的虛擬執行緒
image-20221021083635218
  • 自己寫的Dockerile檔名為Dockerfile.19,內容如下,可見非常簡單:先換基礎映象,再把mvn構建結果複製過去,最後加個啟動命令就完事兒了(遠不如官方的分層構建節省空間,然而在官方的JDK19映象方案出來之前,先用下面這個將就著用吧)
FROM openjdk:19

ENV LANGUAGE='en_US:en'

# 執行工作目錄
WORKDIR application

COPY --chown=185 target/*.jar ./

RUN mkdir config

EXPOSE 8080
USER 185
ENTRYPOINT ["java", "-jar", "--enable-preview", "quarkus-virual-threads-demo-1.0-SNAPSHOT-runner.jar"]
  • 接下來可以製作映象了,請確保自己電腦上docker已在執行

  • 首先是常規maven編譯打包(uber-jar表示生成的jar中包含了所有依賴庫)

mvn clean package -U -DskipTests -Dquarkus.package.type=uber-jar
  • 構建docker映象
docker build -f src/main/docker/Dockerfile.19 -t bolingcavalry/quarkus-virual-threads-demo:0.0.2 .
  • 映象製作成功,控制檯輸出如下圖
image-20221022072718957
  • 如果您有hub.docker.com的賬號,也可以像我一樣推播到公共倉庫,方便大家使用

異常測試(沒有enable-preview引數會怎麼樣?)

  • 回顧Dockerfile中啟動應用的命令,由於虛擬執行緒是JDK19的預覽功能,因此必須新增下圖紅色箭頭所指的--enable-preview引數才能讓虛擬執行緒功能生效
image-20221022073455393
  • 於是我就在想:不加這個引數會咋樣?也就是不開啟虛擬執行緒,但是程式碼中卻要用它,那麼真正執行的時候會如何呢?
  • 瞎猜是沒用的,還是試試吧,在啟動引數中刪除--enable-preview,如下圖,再重新構建映象
image-20221022074847459
  • 像前文那樣執行容器(再次提醒,確保資料庫是正常的),再在瀏覽器存取http://localhost:8080/vt/persons/1,頁面正常顯示了,看來功能是不受影響的
image-20221022082633379
  • 再用docker logs命令檢視後臺紀錄檔,如下圖箭頭所示,quarkus給出了WARN級別的提示:由於當前虛擬機器器不支援虛擬執行緒,改為使用預設的阻塞來執行業務邏輯
image-20221022075007690
  • 小結:在不支援虛擬執行緒的環境強行使用虛擬執行緒,quarkus會選擇相容的方式繼續完成任務

小結和展望

  • 至此,一個完整的quarkus應用已開發完成,該應用使用虛擬執行緒來響應web請求,而且在quarkus官方還沒有提供方案的前提下,咱們依舊完成了docker映象的製作,最後,因為好奇,還關閉重要引數嘗試了一下,一系列操作下來,相信您已經對基礎開發瞭如指掌了

  • 最後,還剩下兩個遺留問題,相信您也會有類似困惑

    1. 虛擬執行緒和常規子執行緒的區別,究竟能不能看出來?前文已經驗證了效能上區別不大,那還有別的方式來觀察和區分嗎?
    2. 能不能稍微深入一點,僅憑一個@RunOnVirtualThread註解就強行寫了兩篇部落格,實在是太忽悠人了
  • 以上問題會在接下來的《支援JDK19虛擬執行緒的web框架,終篇》得到解決,還是那句熟悉的廣告詞:欣宸原創,不辜負您的期待

歡迎關注部落格園:程式設計師欣宸

學習路上,你不孤單,欣宸原創一路相伴...