概述
- Quarkus首頁放出的標(biāo)語:超音速亞原子的JAVA(Supersonic Subatomic Java),它是為OpenJDK HotSpot和GraalVM量身定制的Kube.NETes Native Java框架,基于同類最佳的 Java 庫和標(biāo)準(zhǔn)制作而成。
- Quarkus的到來為開發(fā)linux容器和 kubernetes 原生Java微服務(wù)帶來了一個(gè)創(chuàng)新平臺。
- Spring Boot是一個(gè)基于Java的框架,專注于企業(yè)應(yīng)用,它可以簡單使用所有Spring項(xiàng)目,并集成了許多開箱即用的功能,來幫助開發(fā)人員提高生產(chǎn)力。
- Spring Boot由于其約定優(yōu)于配置方法,它根據(jù)依賴項(xiàng)自動(dòng)注冊默認(rèn)配置,大大縮短了Java應(yīng)用程序的開發(fā)周期。
- Java生態(tài)中新興的技術(shù)體系:
Spring Reactive(Spring WebFlux) → 背靠 Pivotal → 歸屬 VMware → 歸屬戴爾
Quarkus 和 Vert.x → 背靠 Eclipse 基金會 → 主要由 Red Hat 支持
Helidon → 背靠 Oracle
Micronaut → 背靠 Object Computing(GrAIls、OpenDDS)
Lagom → 背靠 Lightbend(Akka)
- 本文重點(diǎn)關(guān)注比較熱門的Spring Reactive和Quarkus在原生鏡像方面的差異。
對比分析
- 創(chuàng)新和生態(tài)系統(tǒng): Spring 有著長期的歷史和豐富的生態(tài)系統(tǒng),許多開發(fā)者對其已經(jīng)非常熟悉。Spring Native 是 Spring 團(tuán)隊(duì)為了更好地適應(yīng)云原生環(huán)境(如 Kubernetes)而推出的新項(xiàng)目。相比之下,Quarkus 較新,但它在設(shè)計(jì)上就考慮了現(xiàn)代云原生和微服務(wù)架構(gòu),因此在某些方面可能更具創(chuàng)新性。
- 性能和資源利用: Quarkus 和 Spring Native 都聲稱可以提供更快的啟動(dòng)時(shí)間和減少的內(nèi)存占用。然而,實(shí)際表現(xiàn)可能會因應(yīng)用程序的具體情況以及你如何使用這些框架而變化。
- 開發(fā)體驗(yàn): Quarkus 提供的開發(fā)模式(live coding)允許開發(fā)者在不重啟應(yīng)用的情況下實(shí)時(shí)看到代碼改變的效果,這可能會提高開發(fā)效率。Spring Native 則繼承了 Spring Boot 的開發(fā)體驗(yàn),使得許多開發(fā)者能夠很快上手。
- 兼容性: Spring Native 對于 Spring 生態(tài)中的部分庫可能還存在兼容性問題,需要按照官方給出的指引進(jìn)行調(diào)整。而 Quarkus 在設(shè)計(jì)時(shí)就盡可能考慮了廣泛的兼容性,包括對于 Hibernate,Apache Camel,Eclipse MicroProfile 等開源庫的支持。
啟動(dòng)&構(gòu)建指標(biāo)對比
啟動(dòng)&構(gòu)建指標(biāo)對比
性能測試
資源版本
- MySQL: 8.0.32-1.el8
- Quarkus: 3.2.2.Final
- Spring Boot: 3.1.2
- JDK: 17.0.8
- Docker Engine: 24.0.5
- Docker Resource: 4C/8G
壓測源碼&鏡像
- 壓測源碼:Github - guanyang/spring-project-samples: 基于springboot3.0及jdk17構(gòu)建常用示例工程
native-sample: 基于spring native構(gòu)建原生鏡像示例
quarkus-sample: 基于quarkus構(gòu)建原生鏡像示例
- 鏡像資源
Quarkus Native Image: guanyangsunlight/spring-project-samples:quarkus-sample-0.0.1-SNAPSHOT
Quarkus JVM Image: guanyangsunlight/spring-project-samples:quarkus-sample-0.0.1-SNAPSHOT-jvm
Spring Boot Native Image: guanyangsunlight/spring-project-samples:native-sample-0.0.1-SNAPSHOT
Spring Boot JVM Image: guanyangsunlight/spring-project-samples:native-sample-0.0.1-SNAPSHOT-jvm
MySQL Image: guanyangsunlight/spring-project-samples:sample-mysql-8.0.32
- Docker Compose文件
quarkus-sample: quarkus-sample/src/main/docker/docker-compose.yml
native-sample: native-sample/src/main/docker/docker-compose.yml
壓測架構(gòu)
壓測架構(gòu)
- 應(yīng)用容器:Spring Boot Native,Quarkus Native,Spring Boot JVM,Quarkus JVM每個(gè)一個(gè)實(shí)例
- MySQL容器:Mysql8.0容器實(shí)例一個(gè)
- K6施壓機(jī): 2.2 GHz 四核Intel Core i7,16 GB 1600 MHz DDR3
- K6參考鏈接:k6 Documentation
壓測場景case
- Spring Boot Native: 性能指標(biāo)(QPS、RT),機(jī)器指標(biāo)(CPU、內(nèi)存)
- Quarkus Native: 性能指標(biāo)(QPS、RT),機(jī)器指標(biāo)(CPU、內(nèi)存)
- Spring Boot JVM: 性能指標(biāo)(QPS、RT),機(jī)器指標(biāo)(CPU、內(nèi)存)
- Quarkus JVM: 性能指標(biāo)(QPS、RT),機(jī)器指標(biāo)(CPU、內(nèi)存)
壓測服務(wù)接口
- 接口地址:${host}/api/test/get/{id}
- 接口說明:根據(jù)id查詢數(shù)據(jù)庫記錄,host為服務(wù)地址,id為數(shù)據(jù)庫記錄主鍵
- 響應(yīng)示例:
{
"code": 200,
"message": "OK",
"data": {
"id": 4,
"version": 1,
"deleted": 0,
"createBy": "admin",
"updateBy": "admin",
"createTime": 1695312514000,
"updateTime": 1695312532000,
"username": "test41"
}
}
壓測腳本
- 總請求時(shí)長300s,并發(fā)從50開始,并按照50步長增長,命令如下:
k6 run -u 50 --duration 300s -e url=http://127.0.0.1:8082/api/test/get/4 simple-test.js
-i:指定請求數(shù)量
-u:模擬并發(fā)數(shù)量
--duration:請求時(shí)長定義,例如:60s,1m
-e url:指定環(huán)境變量url,用于實(shí)際場景替換
- 腳本輸出樣例
scenarIOS: (100.00%) 1 scenario, 50 max VUs, 36s max duration (incl. graceful stop):
* default: 50 looping VUs for 6s (gracefulStop: 30s)
? is status 200
checks.........................: 100.00% ? 7761 ? 0
data_received..................: 1.9 MB 324 kB/s
data_sent......................: 730 kB 121 kB/s
http_req_blocked...............: avg=12.22µs min=1µs med=3µs max=3.26ms p(90)=5µs p(95)=6µs
http_req_connecting............: avg=7.1µs min=0s med=0s max=2.19ms p(90)=0s p(95)=0s
http_req_duration..............: avg=38.56ms min=7.55ms med=34.26ms max=216.77ms p(90)=58.96ms p(95)=68.51ms
{ expected_response:true }...: avg=38.56ms min=7.55ms med=34.26ms max=216.77ms p(90)=58.96ms p(95)=68.51ms
http_req_failed................: 0.00% ? 0 ? 7761
http_req_receiving.............: avg=52.57µs min=19µs med=46µs max=680µs p(90)=81µs p(95)=97µs
http_req_sending...............: avg=19.87µs min=7µs med=16µs max=1.27ms p(90)=27µs p(95)=38µs
http_req_tls_handshaking.......: avg=0s min=0s med=0s max=0s p(90)=0s p(95)=0s
http_req_waiting...............: avg=38.49ms min=7.51ms med=34.18ms max=216.58ms p(90)=58.89ms p(95)=68.46ms
http_reqs......................: 7761 1288.780058/s
iteration_duration.............: avg=38.7ms min=7.76ms med=34.4ms max=218.51ms p(90)=59.08ms p(95)=68.64ms
iterations.....................: 7761 1288.780058/s
vus............................: 50 min=50 max=50
vus_max........................: 50 min=50 max=50
- simple-test.js腳本說明
import http from 'k6/http';
import { check } from 'k6';
export default function () {
const res = http.get(`${__ENV.url}`);
check(res, {
'is status 200': (r) => r.status === 200
});
}
壓測指標(biāo)
被壓機(jī)器指標(biāo)
- CPU usage
- Memory usage
被壓機(jī)器性能指標(biāo)
- QPS
- Avg Latency(ms)
- P95(ms)
壓測結(jié)果
壓測結(jié)果
壓測總結(jié)
- Quarkus Native相較于Spring Boot Native資源消耗更低,性能更好。
- Quarkus JVM相較于Spring Boot JVM模式資源消耗更低,性能更好。
- Native原生相較于JVM模式整體資源消耗更低,啟動(dòng)更快,構(gòu)建鏡像更小。
優(yōu)缺點(diǎn)及選型總結(jié)
Quarkus優(yōu)缺點(diǎn)
- 優(yōu)點(diǎn)高度優(yōu)化的運(yùn)行時(shí)性能和內(nèi)存管理;對于開發(fā)者友好的開發(fā)模式,如實(shí)時(shí)編程(live coding);廣泛的兼容性,支持許多主流的 Java 開源庫;面向云原生應(yīng)用的設(shè)計(jì)。
- 缺點(diǎn)相對于 Spring,其社區(qū)規(guī)模還較小,可能在某些問題上找不到即時(shí)的幫助;盡管有廣泛的兼容性,但并不包括所有的 Java 庫。
Spring Boot Native優(yōu)缺點(diǎn)
- 優(yōu)點(diǎn)建立在 Spring 生態(tài)系統(tǒng)之上,易于為已經(jīng)使用 Spring 的團(tuán)隊(duì)接受;與 Spring Boot 無縫集成,并且借助 GraalVM 提供媲美本機(jī)語言的啟動(dòng)速度和內(nèi)存占用。支持 AOT(Ahead-of-Time Compilation)編譯,可以提高啟動(dòng)速度。
- 缺點(diǎn)使用 Spring Boot Native 需要適應(yīng)其構(gòu)建過程中將應(yīng)用程序轉(zhuǎn)化為本地應(yīng)用程序的復(fù)雜性;構(gòu)建完成的應(yīng)用程序雖然啟動(dòng)速度快、內(nèi)存消耗低,但CPU使用率高于普通 JVM 程序。
技術(shù)選型思考
- 項(xiàng)目需求:如果項(xiàng)目需要快速啟動(dòng),低內(nèi)存消耗,那么兩者都可以滿足。如果已經(jīng)在使用 Spring Stack,并且想要繼續(xù)保持使用它,那么 Spring Boot Native 會更加合適。如果項(xiàng)目對開發(fā)效率有高要求,那么 Quarkus 可能更符合需求。
- 團(tuán)隊(duì)技能:如果團(tuán)隊(duì)成員已經(jīng)非常熟悉 Spring Stack,那么采用 Spring Boot Native 可能可以減少學(xué)習(xí)曲線。反之,如果團(tuán)隊(duì)愿意嘗試新的技術(shù),并且對響應(yīng)式編程和函數(shù)式編程有興趣,那么選擇 Quarkus 可以是一個(gè)不錯(cuò)的選擇。
- 社區(qū)支持和文檔:Spring 社區(qū)非常活躍,有大量的教程和指南。雖然 Quarkus 比較新,但也在積極擴(kuò)大其社區(qū),并提供了詳細(xì)的文檔。
在實(shí)際決策過程中,最好能夠根據(jù)具體情況進(jìn)行技術(shù)選型,可能的話,可以在小規(guī)模的項(xiàng)目或者原型中嘗試并評估這些框架。
Quarkus對Spring開發(fā)者的額外好處
- 功能即服務(wù) (FaaS):當(dāng)編譯為原生二進(jìn)制文件時(shí),Quarkus 應(yīng)用程序可以在 0.0015 秒內(nèi)啟動(dòng),從而可以將現(xiàn)有的 Spring 和 Java API 知識與 FaaS 功能結(jié)合使用。(Azure Functions - Quarkus,AWS Lambda - Quarkus)
- 實(shí)時(shí)編碼:從“Hello World”示例應(yīng)用程序開始,然后將其轉(zhuǎn)換為復(fù)雜的微服務(wù),而無需重新啟動(dòng)應(yīng)用程序。只需保存并重新加載瀏覽器即可查看沿途的變化。 Quarkus 實(shí)時(shí)編碼“開箱即用”,與 IDE 無關(guān)。
- 支持反應(yīng)式和命令式模型:Quarkus有一個(gè)反應(yīng)式核心,支持傳統(tǒng)的命令式模型、反應(yīng)式模型,或在同一應(yīng)用程序中同時(shí)支持兩者。
- 早期檢測依賴注入錯(cuò)誤:Quarkus 在編譯期間而不是在運(yùn)行時(shí)捕獲依賴項(xiàng)注入錯(cuò)誤。
- 最佳框架和標(biāo)準(zhǔn)的結(jié)合:Quarkus 在同一應(yīng)用程序中支持 Spring API 兼容性、Eclipse Vert.x、MicroProfile(JAX-RS、CDI 等)、反應(yīng)式流和消息傳遞等。參考《Autowire MicroProfile into Spring with Quarkus | Red Hat Developer》,可以在一個(gè)項(xiàng)目中同時(shí)使用 Spring 和 MicroProfile API。
參考文檔
- Quarkus vs. Spring Boot | LogicMonitor
- Quarkus for Spring Developers - Quarkus
- Guides - Latest - Quarkus
- Get Started - Quarkus
- Quarkus - Start coding with code.quarkus.io
- Spring Boot Maven Plugin Documentation
- GraalVM Native Image Support
- Getting Started | Building a Reactive RESTful Web Service