來源:medium.com/@egorponomarev
Spring Boot 3.2 前幾日發(fā)布,讓我們用 Java 21、GraalVM 和虛擬線程來嘗試一下。
Spring Boot 3.2 支持:
Java 21
虛擬線程
原生鏡像(自 2022 年 11 月 Spring Boot 3.0 發(fā)布以來,Spring Boot 已在生產(chǎn)環(huán)境中支持 GraalVM 原生鏡像)
Java 21
我們期待 2023 年 9 月 19 日發(fā)布的 Java 21,Spring Boot 3.2 已經(jīng)做到完全支持了。
正如所聲明的那樣,Java 21 提供了數(shù)千項(xiàng)性能、穩(wěn)定性和安全性改進(jìn),包括平臺增強(qiáng)功能,可幫助開發(fā)人員提高生產(chǎn)力并推動整個組織的創(chuàng)新和增長。
虛擬線程
更重要的更新之一是虛擬線程,這是 Project Loom 提供的功能。我們不打算深入細(xì)節(jié),官方 JEP 提供了很好的解釋:
GraalVM 和本機(jī)鏡像
GraalVM 是一種高性能 JDK,可以使用替代的即時 (JIT) 編譯器來加快 Java 和基于 JVM 的應(yīng)用程序的性能。
Native Image 是一種提前將 Java 代碼編譯為獨(dú)立可執(zhí)行文件(稱為本機(jī)映像)的技術(shù)。該可執(zhí)行文件包括應(yīng)用程序類、其依賴項(xiàng)中的類、運(yùn)行時庫類以及來自 JDK 的靜態(tài)鏈接本機(jī)代碼。
它不在 Java VM 上運(yùn)行,但包含來自不同運(yùn)行時系統(tǒng)的必要組件,如內(nèi)存管理、線程調(diào)度等。與 JVM 相比,生成的程序具有更快的啟動時間和更低的運(yùn)行時內(nèi)存開銷。
嘗鮮一下
讓我們從安裝 Java 21.0.1 graal 開始,最簡單的方法是使用SDKMAN 并將其指定為您機(jī)器的默認(rèn) Java 版本:
sdk install java 21.0.1-graal
sdk default java 21.0.1-graal
另一種安裝方法是手動下載
我們將使用Spring Initializr頁面創(chuàng)建一個新的Spring Boot項(xiàng)目,使用 Spring Boot 3.2.0、Java 21、Gradle-Groovy以及Spring Web和GraalVM本地支持依賴項(xiàng)。
要在 Spring Boot 3.2 中啟用虛擬線程,我們只需在 application.yml 或 application.properties 文件中設(shè)置一個屬性:
spring.threads.virtual.enabled:true
這個配置起到的作用:
Tomcat 將使用虛擬線程來處理 HTTP 請求。這意味著處理 Web 請求的應(yīng)用程序代碼(例如控制器中的方法)將在虛擬線程上運(yùn)行。
調(diào)用@Async方法時,Spring MVC 的異步請求處理和 Spring WebFlux 的阻塞執(zhí)行支持現(xiàn)在將利用虛擬線程
標(biāo)記有@Scheduled的方法將在虛擬線程上運(yùn)行
因此,我們將嘗試使用這 3 個集成來實(shí)現(xiàn)虛擬線程。
此外,一些特定的集成將在虛擬線程上工作,例如 RabbitMQ/Kafka 監(jiān)聽器,以及 Spring Data Redis/Apache pulsar 相關(guān)的集成。但這些集成超出了本文的范圍,有興趣的可以參考 Spring Boot 3.2 官方示例。
代碼
1.對于 Tomcat 傳入的 HTTP 請求,我們創(chuàng)建一個簡單的控制器:
@RestController @RequestMapping("/test") publicclassTestController{ privatestaticfinalLoggerlog=LoggerFactory.getLogger(TestController.class); @GetMapping publicvoidtest(){ log.info("Restcontrollermethodhasbeencalled{}",Thread.currentThread()); } }
2.異步任務(wù)
我們將在應(yīng)用程序啟動時調(diào)用其“run”方法
@Component publicclassAsyncTaskExecutorService{ privatestaticfinalLoggerlog=LoggerFactory.getLogger(AsyncTaskExecutorService.class); @Async publicvoidrun(){ log.info("Asynctaskmethodhasbeencalled{}",Thread.currentThread()); } }
3.Scheduled 定時任務(wù)
一個簡單的方法,每 15 秒調(diào)用一次
@Component publicclassSchedulerService{ privatestaticfinalLoggerlog=LoggerFactory.getLogger(SchedulerService.class); @Scheduled(fixedDelayString="15000") publicvoidrun(){ log.info("Scheduledmethodhasbeencalled{}",Thread.currentThread()); } }
讓我們運(yùn)行我們的應(yīng)用程序:
./gradlewbootRun
并調(diào)用我們的端點(diǎn)
curl—位置—請求GET'localhost:8085/test'
我們得到什么:
StartingAppApplicationusingJava21.0.1withPID38126 StartedAppApplicationin1.131seconds(processrunningfor1.491) AsynctaskmethodhasbeencalledVirtualThread[#52,task-1]/runnable@ForkJoinPool-1-worker-5 ScheduledmethodhasbeencalledVirtualThread[#46,scheduling-1]/runnable@ForkJoinPool-1-worker-1 RestcontrollermethodhasbeencalledVirtualThread[#62,tomcat-handler-0]/runnable@ForkJoinPool-1-worker-1 ScheduledmethodhasbeencalledVirtualThread[#46,scheduling-1]/runnable@ForkJoinPool-1-worker-1
我們可以看到我們的方法的日志鏈接到公共 ForkJoinPool 線程池。
根據(jù)JEP:預(yù)期行為:
JDK 的虛擬線程調(diào)度程序是一個工作竊取的 ForkJoinPool,它以 FIFO 模式運(yùn)行。調(diào)度程序的并行度是可用于調(diào)度虛擬線程的平臺線程的數(shù)量。
現(xiàn)在讓我們在 GraalVM 上運(yùn)行它。
首先,我們需要構(gòu)建一個 GraalVM 本機(jī)映像:(此命令可能需要幾分鐘)然后運(yùn)行:(使用您的應(yīng)用程序的名稱而不是“app”)
./gradlewnativeCompile ./build/native/nativeComplie/app
它也可以工作,并且啟動時間要快得多,這符合聲明的“與 JVM 相比,生成的程序具有更快的啟動時間和更低的運(yùn)行時內(nèi)存開銷”。
在這里您可以找到包含本文中使用的代碼的存儲庫來源
結(jié)論
Spring Boot 3.2 是我們一直在等待的東西!具有虛擬線程的本機(jī)映像允許我們編寫能夠提供與 Go 類似級別的性能和可擴(kuò)展性的代碼,從而保持 JVM 的強(qiáng)大生態(tài)系統(tǒng)。
但是,您必須考慮到并非所有庫都已采用其代碼來與虛擬線程正常工作(在大多數(shù)情況下,它正在用 ReentrantLock 替換“synchronize”塊),您應(yīng)該小心虛擬線程將使用的邏輯。
審核編輯:湯梓紅
-
JAVA
+關(guān)注
關(guān)注
19文章
2967瀏覽量
104748 -
線程
+關(guān)注
關(guān)注
0文章
504瀏覽量
19682 -
鏡像
+關(guān)注
關(guān)注
0文章
164瀏覽量
10717 -
SpringBoot
+關(guān)注
關(guān)注
0文章
173瀏覽量
178
原文標(biāo)題:Spring Boot 3.2 正式發(fā)布,開箱即用的虛擬線程和 GraalVM,嘗鮮一下!
文章出處:【微信號:芋道源碼,微信公眾號:芋道源碼】歡迎添加關(guān)注!文章轉(zhuǎn)載請注明出處。
發(fā)布評論請先 登錄
相關(guān)推薦
評論