2020年你將會選擇哪一個微服務框架?

前言

截至2020年,Java仍然是構建Web應用程序的最流行的編程語言之一,儘管它必須面對來自Go,Python和TypeScript等新型語言的激烈競爭。java

在Java世界內部,Spring框架已成爲微服務開發的事實上的標準,經過諸如Spring Boot和Spring Data之類的庫,該框架易於使用,而且能夠進行高效且大部分狀況下輕鬆進行開發。git

可是,近年來,已經引入了新的框架,聲稱能夠縮短Java應用程序的啓動時間並減小其內存佔用。因爲我目前正在使用Java開發基於微服務的大型應用程序,所以我想測試哪一種Java框架最適合這種架構。github

所以,個人主要重點是開發的易用性以及微服務的資源消耗兩個方面。spring

對於資源消耗方面,Spring一直都被人詬病,尤爲是在涉及單個流程所需的資源開銷。在應用程序服務器時代,因爲實例數量不多,所以這並非主要問題。可是,隨着微服務架構及其大量小型實例的興起,這個問題變得愈來愈明顯。正如Christian Lusardi最近所說的那樣:docker

「我發現使用Spring Boot運行的基本Java應用程序至少須要1GB的RAM,開發中間件應用程序不要緊,可是在微服務體系結構中,這很是糟糕!」數據庫

微服務框架介紹

1 Spring

爲了解決早期Java Enterprise的複雜性,Spring於2003年應運而生。Spring核心是依賴注入(DI)和麪向切面編程(AOP),後來衍生出易於使用的Spring MVC等Web應用框架。經過其良好的文檔,全面的各方面整合類庫,Spring使開發人員能夠有效地建立和維護應用程序,並提供平坦的學習曲線。編程

Spring在運行時使用反射執行DI。所以,當啓動spring應用程序時,將在類路徑中掃描帶註解的類。基於此,實例化並連接到具體對象。這種作法很是靈活且對開發人員很友好,但它可能使得啓動過程緩慢並佔用大量內存。另外,將這種機制遷移到GraalVM很是困難,由於GraalVM不支持反射。安全

2 Micronaut

Micronaut是比較新的全棧微服務框架,由Grails框架的建立者於2018年引入。服務器

Micronaut提供了構建功能全面的微服務應用程序所需的全部工具。同時,它旨在提供快速啓動並減小內存佔用。經過使用Java註解處理器執行DI,建立面向切面的代理(而不是運行時)配置應用程序,能夠實現此目標。架構

Micronaut中的許多API均受Spring和Grails的啓發。這無可厚非,畢竟這樣有助於快速吸引Spring及Grails的開發人員。Micronaut提供了諸如Micronaut HTTP,數據,安全性和各類其餘技術的鏈接器之類的模塊。可是,這些庫的成熟度仍落後於Spring的同類庫。

3 Quarkus

Quarkus是Red Hat在2019年引入的Kubernetes原生Java框架。它基於MicroProfile,Vert.x,Netty和Hibernate等標準構建。

Quarkus的目標是經過在容器編排平臺中容許更快的啓動,較低的內存消耗和近乎即時的擴展來使Java成爲Kubernetes中的領先平臺。Quarkus經過使用自定義的Maven插件在編譯時而不是在構建時執行儘量多的工做來達到此目的(在Quarkus中,這也稱爲編譯時啓動)。

Quarkus使用了大多數現有的標準技術,並且還支持擴展。可是,因爲該項目僅在一年以前纔開始,因此這些擴展的成熟度和兼容性並不老是很清楚。隨着平臺的發展,這種狀況未來可能會改變。

4 Helidon MicroProfile

MicroProfile項目立項於2016年,與其前身JEE同樣,MicroProfile是能夠由各類供應商實施的規範。到目前爲止,MicroProfile規範已經提出了多種實現方式,最著名的是Payara Micro和Helidon MP。

Payara是從GlassFish派生的Jakarte EE服務器,而Payara Micro是其MicroProfile實現。Helidon是Oracle在2018年啓動的運行時,提供了本身的MicroProfile規範實現。

因爲它們是從JEE派生的,所以MicroProfile規範已經很成熟而且有據可查。可是,缺乏用於現代技術的鏈接器或替代諸如Spring Data和Spring Security之類的庫的方法。

此外,因爲同時開始了Jakarta EE(也在Eclipse Foundation中)的開發,MicroProfile的將來尚不清楚。所以,彷佛兩個項目未來可能會合並。

微服務框架全方位大PK!

爲了比較上述4個微服務框架,我已經使用它們實現了一個簡單的應用程序。該示例應用程序包括一個用於建立,讀取,更新和刪除對象的REST接口,以及將這些對象存儲到表中的接口。我使用OpenJDK Docker映像運行了全部應用程序。若是該框架支持生成本機GraalVM映像,我也比較了它們的性能。

我在如下幾個方面對比了它們的性能:

  1. 把上述的示例應用程序開發出來要多久?要實現這些框架,我必須查看框架官方文檔以及在諸如Stack Overflow之類的平臺上搜索信息。
  2. 編譯應用程序須要多長時間?我已經測試了執行乾淨構建所需的時間,包括生成Docker映像。對於GraalVM,這包括生成本機映像的時間。
  3. 啓動應用程序須要多長時間?在這裏,我測試了從運行docker up到應用程序正確響應第一個HTTP請求之間的時間。另外,我還比較了啓動後測試的空閒應用程序的內存佔用量。
  4. 應用程序支持請求負載狀況如何?我使用JMeter進行負載測試,並對應用程序進行了測試,其中25%的請求執行數據庫寫入,而75%的請求僅執行數據庫讀取。而後,我再次根據其峯值性能來測量應用程序的內存佔用量。

我在具備四個Intel Haswell CPU和15 GB內存且運行Ubuntu 19.01的Google Cloud Platform虛擬機上執行了全部測試。全部測量均已重複屢次,以免干擾因素。您能夠在GitHub上找到使用的腳本以及原始數據。

https://github.com/lizzyTheLizard/medium-java-framework-compare/tree/master/compare

測試結果

1 上手難度

因爲我之前就有Spring Boot的知識,因此這是一個不公平的比較。可是,在查詢文檔以及可用的信息和示例時,Spring確實是迄今爲止使用起來最簡單的框架。

Micronaut的文檔作得很好,而且具備與Spring和Grail相似的API。所以,Spring開發人員很容易開始使用它。

我認爲,Quarkus的學習曲線較爲陡峭,由於與Spring和Micronaut相比,庫和API的成熟度較低。我特別缺乏簡單的數據庫訪問權限。

在我看來,Helidon顯然是最後一名,由於我爲應用程序運行付出了很大的努力。

2 編譯時間

全部框架,使用OpenJDK時的編譯時間都很是類似,而且在6.98秒(使用JDBC的Spring)和10.7秒(Quarkus)之間。

可是,原始GraalVM映像的生成很是耗時,花費了231.2秒(使用JDBC的Micronaut)和351.7秒(使用JPA的Micronaut)之間。這使得本機映像對於開發基本上毫無用處,由於等待四分鐘來編譯一個簡單的應用程序實在太多了。

3 啓動運行時間

使用Spring Data的Spring Boot應用程序平均花了8.16秒來啓動。刪除JPA和Spring Data能夠將其減小到5.8秒。

正如官方所說,Micronaut(使用JPA的時間爲5.08秒,使用JDBC的時間爲3.8秒)和Quarkus(5.7秒)都保證了縮短啓動時間的承諾。

Helidon MP甚至比Spring慢-平均耗時爲8.27秒。

可是,真正的贏家是GraalVM。本機映像的啓動時間在1.39秒(Quarkus)和1.46秒(使用JDBC的Micronaut)之間,比OpenJDK實現要快得多。

全部框架運行時使用的內存使用狀況很是類似。Spring分配了420 MB內存(使用Spring Data)和261 MB(使用JDBC)。使用JPA時Micronaut的內存爲262 MB,使用JDBC時爲178 MB。197 MB的Quarkus表現更好。Helidon MP耗時414 MB,與Spring Boot相似。

一樣,僅使用7 MB(Quarkus)和27 MB(Micronaut使用JPA)的內存,原生GraalVM映像的表現大大優於OpenJDK。

4 峯值負載性能

在負載下,Spring Boot表現出色,可以處理每秒342(使用Spring Data)和216(JDBC)請求(r/s),並使用581 MB(Spring Data)和484 MB(JDBC)內存。Helidon顯然是最後一名,只能提供175 r/s的速度,同時分配超過1 GB的內存。

其餘框架可以在400 r/s(Quarkus做爲本機映像運行)和197 r/s(OpenJDK上的Quarkus)之間提供服務。各類Micronaut實現介於二者之間,與JDBC相比,JPA和本機映像比OpenJDK略有優點。

在內存使用方面,OpenJDK上的Quarkus表現出色,僅消耗255 MB內存。這甚至比同一個應用程序做爲本機映像運行要少得多,該應用程序平均花費368 MB的內存。

可是,Micronaut卻很是浪費。在OpenJDK中運行的JPA實現平均使用880 MB,比Spring的內存使用量高50%以上。可是,使用JDBC和本機映像有助於Micronaut將其內存佔用空間減小到367.8 MB。

結論

與Spring和MicroProfile之類的現有框架相比,新的Java框架Micronaut和Quarkus保證了更快的啓動時間和更低的內存佔用。

他們的確兌現了這一諾言-但只有在閒置或負載很小的狀況下才能夠。在這裏,它們的性能優於Spring,特別是將它們與本地GraalVM圖像結合使用時。可是,在高負載下,它們即便在做爲本機映像運行時也沒法提供太多優點。

到目前爲止,Spring在開發上給Java開發者最佳體驗,並且我認爲它也仍然是最適合微服務應用程序的Java框架(即便啓動時的性能比較差)。

讓我感到驚訝的是,使用Hibernate / JPA / Spring Data的成本很是高。即便對於這個很是簡單的應用程序,在內存(以及r/s)方面的開銷也是巨大的。在這裏,我特別喜歡Micronaut Data的解決方案,該解決方案無需JPA便可自動生成Dao代碼。我認爲Micronaut Data之後能夠添加到Spring Data方案中。

事實證實,本機GraalVM映像在啓動時具備使人難以置信的快速性和內存效率,可是在負載下,它們並無明顯的優點。因爲本機GraalVM的生成會帶來一些額外的困難,而且編譯時間會急劇增長,所以該技術目前僅在須要快速啓動時纔有用。例如在Serviceless架構中。

歡迎關注個人公衆號::一點教程。得到獨家整理的學習資源和平常乾貨推送。

若是您對個人系列教程感興趣,也能夠關注個人網站:yiidian.com

相關文章
相關標籤/搜索