導讀:
在萬物云原生下的環境下,Java的市場份額也因耗資源、啟動慢等缺點,導致在云原生環境里被放大而降低,通過這篇文章,讀者可以更好地了解如何在云原生環境下通過升級相關版本和使用GraalVM打出原生鏡像到方式,優化Java應用的性能和資源利用率,使Java應用更好地適應云原生環境,
1.引言(Introduction)
1.1、目的:
現在我們的專案能正常運行,為什么要耗費大量人力重構?
1.2、背景:
云原生時代下和java的愛恨情仇:

在云原生時代,隨著技術的日新月異變化,我們尋找最佳技術解決方案的道路上總是充滿坎坷,作為分布式應用的主流技術,Kubernetes(簡稱k8s)和Java在這個時代交織出一段愛恨情仇般的佳話,那云原生下這兩個技術究竟是敵是友,需要我們進行深入分析,首先,我們站在云原生的角度來看,難以忽視的是k8s 的確被時代認可,尤其在微服務架構、容器化部署和資源管理等方面,其強大的自動化、彈性伸縮和容錯能力成為了很多軟體系統的最佳實踐,而Java作為一門擁有28多年歷史的編程語言,無論是在市場份額和生態圈都有無可撼動的地位,Java在分布式系統、中間件、業務邏輯處理等方面有著豐富的實踐經驗,為開發人員提供了良好的編程體驗和廣闊的生態支持,而在眾多應用架構的背后的技術架構都離不開Kubernetes和Java,從這個角度看來,它們似乎是一對黃金搭檔,但關系到具體實踐程序時,細節往往能決定成敗,我們來看看這兩個技術在實際操作中產生的愛恨情仇,
1.2.1、 愛與恨:資源限制與管理
在云原生架構中,k8s為應用提供了資源限制與管理的能力,使得應用能夠按需分配資源,然而,Java在處理資源方面存在一定的局限性,因為JVM在記憶體管理方面依賴于Xms和Xmx等引數進行配置,導致應用在Kubernetes中的資源管理相對復雜,在這期間我們發現java也不甘示弱 在JVM層面對資源管理等方面也進行了改進 比如增加了Containters標志,使得Java應用在k8s環境中的資源配置更為簡化,
1.2.2、恩怨難分:服務發現與負載均衡
在微服務架構中,服務發現和負載均衡是關鍵,過去,Java生態中有很多解決方案,例如Eureka、Zookeeper等,這讓java在服務發現和負載均衡方面有多種選擇,
但在k8s環境中,天然具備服務發現和負載均衡的能力,如果需要轉到云原生就需要對微服務進行調整以適配k8s環境,
1.2.3、 重逢:持續集成與持續部署(CI/CD)
k8s在持續集成與持續部署方面具備很強的能力,與GitLab、Jenkins等CI/CD工具的結合可以為Java應用提供極致的開發、構建和部署體驗,通過將k8s和Java生態中優秀的CI/CD工具整合在一起,架構師能夠實作敏捷的開發、快速的迭代和高效的運維,
1.2.4、共生:愛恨交織
在k8s的世界里,Java應用程式的部署和管理已然變得越來越高效,但隨著微服務、Serverless 架構的興起,Java的致命缺陷開始暴露出來,首先是啟動時間,Java應用程式在啟動時需要加載眾多類檔案,帶來了相對較長的啟動時間,再者,Java應用程式的記憶體占用往往較高,這在云原生環境中意味著更高的運行成本,然后我們開始尋找替代方案,以求擺脫Java在云原生領域的束縛,進而擁抱更快、更輕量級的應用程式運行環境,
1.2.5、曙光:曾經失去的統統要拿回來
于是,GraalVM應運而生,GraalVM是一個高性能的Runtime,支持多種編程語言(這也是它通用的原因),它提供了Java與云原生領域的橋梁,可以將Java代碼編譯成本地可執行檔案,這意味著更快的啟動速度和更低的記憶體使用,與之同時,GraalVM還提供了對Java的完整支持,便于將現有的Java應用程式遷移到云原生領域,此外,GraalVM還集成了許多強大的特性,如 (AOT)編譯、即時編譯(JIT)以及強大的GC回識訓制,這些特性使得GraalVM成為了在云原生領域的新寵,
2、技術選型:
2.1、五要素:

2.1.1、充分利用現有代碼庫:
如果已經擁有一個功能完備且經過充分測驗的Java應用程式,那么將其轉換為native-image可以最大程度地復用現有代碼庫,減少重新撰寫應用程式所需的作業量和風險,此外我們部門專案都是Java,使用native-image能有效降低遷移成本,
2.1.2、開發者熟悉度:
如果隊伍中已經具備較為豐富的Java開發經驗,那么將Java應用轉換為native-image會降低學習成本和培訓成本,相較于使用全新的編程語言來重寫應用,這會使得開發者更容易上手,
2.1.3、性能優化:
雖然Java應用在某些性能方面可能不如其他編程語言,但通過使用native-image,可以將Java應用轉換為與C或C++等編譯型語言類似的二進制檔案,從而縮小性能差距,native-image為應用帶來更快的啟動速度和更低的記憶體占用,而這在k8s這種容器化的環境中尤為重要,
2.1.4、 跨平臺能力:
Java具有良好的跨平臺兼容性,而借助GraalVM進行native-image編譯,我們依然可以保留這一特性,這為應用部署提供較高的靈活性,降低了環境遷移和維護的復雜度,
2.1.5、 開發和生態系統:
Java擁有龐大的開發社區和一個成熟、豐富的生態系統,提供了大量的庫和框架來支持各種應用的開發,使用native-image可以更好地利用這些資源,簡化應用的開發和維護程序,
2.1.6、最終方案:
采用jdk17+springboot3+native-iamge=原生輕量化服務
對于低頻流量的業務系統,采用試點專案的方式保證可行性的落地,根據業務功能進行專案合并,而對于合并后的全新專案,直接升級(jdk 和spring框架) version 完成專案合并后保證java版本的專案跑起來,之后采用native-image的方式打包成原生鏡像,讓專案在 新特性/穩定性的版本基礎上 晉升為真正的輕量化應用,
3、概念:
3.1、為什么要升級jdk?
3.1.1、新的語言特性:
JDK 8 到 JDK 17 之間引入了許多新的語言特性和功能,如Lambda 運算式、Stream API、Optional 類、默認方法、介面私有方法等,這些特性可以使代碼更簡潔、可讀性更好,并支持函式式編程風格,提高開發效率和代碼質量,
3.1.2、性能優化和增強:
JDK 17 中進行了多項性能優化和增強,包括垃圾回收器的改進、JIT 編譯器的增強、并發類別庫的改進等,這些優化可以提高應用程式的性能和吞吐量,特別是在大規模和高并發的情況下,
3.1.3、模塊化系統:
JDK 9 引入了模塊化系統(Java Platform Module System,JPMS),它提供了更好的代碼組織和隔離,使得復雜的應用程式可以更容易地維護和擴展,模塊化系統還可以幫助識別和解決潛在的依賴沖突問題,提高應用程式的穩定性和可靠性,
3.1.4、安全性增強:
JDK 17 在安全性方面有多項改進,包括加強的加密演算法(SHA-3、X25519、Ed25519 )、更新的安全協議(TLS 1.3)、安全性增強的 API 等,這些改進可以提升應用程式的安全性,防范潛在的安全漏洞和攻擊,
3.1.5、工具和性能分析:
JDK 17 提供了許多工具和性能分析的改進,例如 JShell(互動式編程工具)、Java Flight Recorder(JFR,低開銷的性能分析工具)、JDK Mission Control(JMC,性能監控和故障診斷工具)等,這些工具可以幫助架構師和開發團隊更好地分析和優化應用程式的性能和行為,
3.1.6、持續改進和穩定性:
從 JDK 8 到 JDK 17,Java 平臺一直在持續改進和演進,JDK 17 是一個長期支持(LTS)版本,意味著它將獲得長期的支持和維護,包括安全更新、錯誤修復和性能改進,作為架構師,選擇升級到 JDK 17 可以獲得更穩定和可靠的平臺,并確保應用程式能夠得到長期的支持,
3.2、為什么要升級springboot組件?
3.2.1、充分利用 JDK 17 的新功能和性能優化:
JDK 17 引入了許多新的功能、改進和性能優化,這些包括新的語言特性、增強的性能和安全性、更好的垃圾回收器、模塊化系統等,通過將 Spring Boot 升級到版本3,可以利用 JDK 17 的新功能,提高應用程式的性能、穩定性和安全性,
3.2.2、支持新的 Java 版本:
Spring Boot 1.x 系列最初是為 JDK 6 和 JDK 7 開發的,而 Spring Boot 2.x 系列則對 JDK 8 有更好的支持,我們將 JDK8 升級到 JDK 17,將 Spring Boot 從版本1.x、2.x升級到版本3,可以確保應用程式能夠充分利用 JDK 17 的新特性,并獲得更好的兼容性和性能,
3.2.3、修復已知的問題和漏洞:
隨著時間的推移,Spring Boot 的新版本會修復舊版本中存在的問題、漏洞和錯誤,通過升級到最新的 Spring Boot 版本,您可以獲得這些修復,并提高應用程式的穩定性和安全性,
3.2.4、社區支持和檔案更新:
隨著時間的推移,Spring Boot 社區會隨著新版本的發布而更新和改進檔案、示例和社區支持,通過升級到最新版本,您可以獲得最新的檔案和社區支持,使您能夠更好地使用和維護 Spring Boot 應用程式,
3.3、升級jdk/springboot可能導致的差異?
3.3.1、API 變動:
JDK 在不同的版本中引入了新的 API,并對舊 API 進行了修改和棄用,在升級到 JDK 17 之前,需要仔細檢查你的代碼,查找并解決所有使用了已棄用的 API 的地方,還應該熟悉 JDK 9、JDK 11、JDK 14 和 JDK 17 之間的主要 API 變動,以便在升級程序中進行必要的修改 (servlet api沒報錯先忽略),
3.3.2、模塊化系統(Module System):
1.JDK 9 引入了模塊化系統,將 JDK 中的功能劃分為一組模塊,如果你的應用程式依賴于 JDK 8 中不存在的模塊,或者使用了模塊化系統中的新特性(如模塊路徑),在升級到 JDK 17 時需要進行相應的調整,確保你的應用程式的模塊宣告和依賴關系與 JDK 17 兼容,并進行必要的遷移作業(jdk8升的忽略),
3.3.3、移除的功能:
JDK 8 到 JDK 17 期間,JDK 團隊可能會移除一些不再支持的功能,在升級之前,查看 JDK 的發布說明和檔案,了解哪些功能將被移除或棄用,檢查你的代碼是否使用了這些功能,以便及時進行修改和適應,
3.3.4、位元組碼和運行時差異:
JDK 17 中引入了一些新的位元組碼指令和運行時優化,這可能會導致你的應用程式在升級后出現不同的行為,特別是在使用反射、位元組碼增強和動態代理等技術的情況下,需要仔細測驗和驗證升級后的應用程式是否仍然正常運行,
3.3.5、第三方庫和工具兼容性:
升級 JDK 可能會對你的應用程式依賴的第三方庫和工具產生影響,在進行升級之前,確保你所使用的所有庫和工具與 JDK 17 兼容,并及時更新到最新版本,此外,還要留意一些特定的庫或工具可能會有與 JDK 版本相關的限制或要求,
3.3.6、性能和穩定性:
升級 JDK 可能會帶來性能改進和 bug 修復,但也可能引入新的性能問題或穩定性問題,在升級之后,通過全面的性能和穩定性測驗,確保你的應用程式在新的 JDK 版,
3.3.7、移除的功能:
如果代碼使用了 JDK 8 中被移除或棄用的功能,查找 JDK 17 的發布說明,找到替代的功能或方法,并進行相應的修改,比如sun.misc.Unsafe 其大部分方法已被標記為 @Deprecated
3.3.8、位元組碼和運行時差異:
在升級到 JDK 17 后,你的應用程式出現了意料之外的行為, 使用除錯工具和日志記錄,對代碼進行詳細調查,查找與位元組碼和運行時差異相關的問題,并進行相應的修復,例如,JDK 17 引入了 instanceof 指令的新變體 instanceof<type>,用于改進 instanceof 運算子的性能,如果你的代碼在 JDK 8 中使用了自定義的位元組碼操作,需要檢查是否需要相應地調整代碼,
3.3.9、依賴項更新:
升級到 Spring Boot 3.x 可能需要更新你的應用程式的依賴項,如 Spring Framework、Hibernate 等,解決方法:查看 Spring Boot 的檔案和依賴項管理,了解每個版本所需的依賴項版本,并更新你的專案組態檔 Maven 以使用相應的版本,確保所有依賴項與 Spring Boot 3.x 兼容,
3.3.10、組態檔變更:
Spring Boot 3.x 可能引入了新的配置屬性或更改了現有屬性的名稱或行為,解決方法:仔細檢查你的應用程式的組態檔,特別是 application.properties 或 application.yml,根據 Spring Boot 的檔案和遷移指南,更新和調整屬性的名稱和用法,
3.3.11、自動配置變動:
Spring Boot 3.x 可能修改了某些自動配置類或默認行為,可能會影響你的應用程式的行為, 查看 Spring Boot 的升級檔案和發布說明,了解哪些自動配置類發生了變化,并在必要時進行相應的修改和調整,
3.3.12、測驗更新:
Spring Boot 3.x 可能引入了新的測驗框架或更改了現有的測驗注解和行為, 查看 Spring Boot 的測驗檔案,了解測驗框架的更新和變化,并相應地修改和調整你的測驗代碼
3.3.13、Spring Boot Starter 的命名變化:
在 Spring Boot 2.x 版本中,許多 Spring Boot Starter 的命名方式發生了變化,例如,原來的 spring-boot-starter-web 變為 spring-boot-starter-webflux,spring-boot-starter-data-jpa 變為 spring-boot-starter-data-jdbc 等,Spring Boot 2.x 中,默認的快取自動配置使用 JCache(JSR-107)作為快取提供者在 Spring Boot 3.x 中,快取自動配置發生了變化,Spring Boot 3.x 引入了對 Caffeine 快取提供者的默認支持
3.4、初探graalvm

3.4.1、GraalVM 社區版(Community Edition):
在社區版和企業版本中,如果不指定GC ,默認都使用的是 Serial GC,而在企業版中可以指定使用 G1 垃圾回收器,G1 垃圾回收器是一種現代化的低延遲垃圾回收器,適用于大部分應用場景,而在在企業版中,引入了名為 GraalVM Native Image 的功能,它使用了不同的垃圾回收器,GraalVM Native Image 是一個 AOT(Ahead of Time)編譯器,可以將 Java 程式編譯成本地機器碼,從而提供更快的啟動時間和更低的記憶體占用,對于 Native Image,GraalVM 企業版使用了垃圾回收器 Substrate VM,它是專門為 AOT 編譯的應用程式設計的,
3.4.2、性能優化:
GraalVM 企業版通常會提供更多的性能優化功能和選項,這包括對即時編譯(Just-in-Time Compilation)的改進、代碼優化和程式分析等方面的增強,企業版的目標是提供更高效、更高性能的運行環境,
3.4.3、工具和擴展:
企業版可能提供一些額外的工具、庫和擴展,以滿足企業級應用程式的需求,這些工具可能包括性能分析器、除錯器、記憶體分析工具和性能監控等,
3.4.4、安全增強:
GraalVM 企業版通常會提供一些安全增強功能,以提供更好的應用程式安全性和保護,這可能包括對代碼審計、漏洞掃描和安全加固方面的支持,
3.4.5、跨語言集成:
企業版可能提供更好的跨語言集成支持,GraalVM 企業版具有更廣泛的語言支持,包括 Java、JavaScript、Python、Ruby 等,使得在混合語言環境中開發和運行應用程式更加便捷,
3.4.6、商業支持和服務:
企業版提供商業支持和服務,包括錯誤修復、安全更新和技術支持,這可以確保您在使用 GraalVM 時獲得及時的支持和幫助,
4、價值:
4.1、直觀價值:
4.1.1、性能提升:
新版本的JDK和Spring Boot通常會引入性能改進和優化,包括記憶體管理、垃圾回收、執行緒處理等方面的優化,這可能會減少應用程式的記憶體占用和CPU負載,從而提高系統的回應速度和吞吐量,再集成native-image 編譯生成的原生鏡像的啟動速度往往比JVM的啟動速度快得多,這對于有很多短暫任務的應用場景(例如serverless或者函式計算)非常有利
4.1.2、記憶體管理和垃圾回收提升:
JDK的每個版本都在記憶體管理和垃圾回收方面進行了改進,新的版本通常會引入更高效的垃圾回收演算法和記憶體管理策略,使應用程式能夠更有效地利用記憶體資源,并減少垃圾回收的停頓時間,這將有助于降低記憶體占用和減少GC相關的CPU開銷,而采用原生鏡像后,通常具有比基于JVM的應用更低的記憶體占用,這有利于降低運行時的資源消耗,
4.1.3、資源優化比提升:
新版本的Spring Boot可能會引入更好的資源管理和優化機制,這包括對資料庫連接、執行緒池、快取等資源的更有效的管理和利用,以減少不必要的資源消耗,提高系統的資源利用率,而使用 native-image 編譯后的本地機器代碼 更加顯著減小應用程式的記憶體占用,因為 native-image 只包含應用程式所需的運行時組件和庫,而不需要整個 JVM 的額外開銷 鏡像大小能減少80%,且編譯后的本地機器代碼不再依賴于 JVM, 減少應用程式對系統資源的消耗,使得應用程式可以在資源受限的環境中更高效地運行,
4.1.4、并發提升:
新版本的JDK和Spring Boot可能會提供更高效的并發處理機制和多執行緒編程模型,這將使應用程式能夠更好地利用多核CPU,并提高并發性能,通過更好的執行緒池管理、異步編程模型等,可以減少不必要的執行緒開銷,提高系統的并發能力,
4.1.5、節省成本:
通過優化資源消耗,尤其是記憶體和CPU,可以降低硬體需求和成本,較低的記憶體占用和CPU負載意味著可以在相同的硬體配置下運行更多的應用實體,從而節省硬體成本,此外,較低的資源消耗還可以減少運維成本和能源消耗,
4.2、長遠價值:
4.2.1、長期支持和維護:
JDK 17是一個長期支持版本(LTS),它將獲得長期的官方支持和維護,包括安全更新、錯誤修復和性能優化,這意味著我們的應用程式可以在未來幾年內持續受到支持,保持安全、穩定和可靠,
4.2.2、技術演進和發展:
通過升級到最新的JDK和Spring Boot版本,可以跟上技術的演進和發展,利用新的語言特性、框架改進和工具,提高開發效率和代碼質量,同時,升級也為我們團隊提供了學習和發展的機會,使他們能夠跟上行業的最新趨勢和技術標準,提高他們的技術能力和知識廣度,
4.2.3、生態系統支持:
隨著時間的推移,與JDK和Spring Boot相關的生態系統將持續發展和壯大,升級到最新版本可以使您能夠獲得更廣泛、更成熟的生態系統支持,這包括更多的第三方庫、工具、插件和社區資源,可以加速開發程序、解決問題和提供更豐富的功能集,
4.2.4、提高開發效率:
新版本通常會引入更多的開發工具和改進,旨在提高開發效率和開發人員的體驗,例如,新的語言特性、API改進、自動化工具和開發作業流程的優化等,都有助于簡化開發任務、減少樣板代碼,并提高團隊的整體生產力,
4.2.5、公司團隊動力和職業發展:
通過升級到最新版本,公司成員可以參與到技術升級的程序中,提出建議、貢獻經驗和共享知識,這有助于增強對公司的積極性和歸屬感,激發他們的職業發展動力,同時也為他們提供學習和成長的機會,
4.2.6、提高公司在互聯網的競爭力:
升級到最新的技術版本可以使部門甚至公司保持在技術的前沿,并具備更強的競爭力,公司將能夠應對新的技術挑戰和專案需求,提供更高質量、更高性能的解決方案,從而在市場上保持競爭優勢,
4.2.7、面向未來的準備:
升級到較新的版本可以幫助您為未來做好準備,您的應用程式可以充分利用新的技術和功能,以滿足不斷變化的業務需求和用戶期望,同時,較新的版本通常會更好地適應新的硬體和部署環境,為您的應用程式提供更好的性能、可擴展性和可靠性,
總結:
總之,升級JDK和Spring Boot版本,以及使用native-image打出來的原生鏡像可以幫助Java應用更好地適應云原生環境,提高應用的性能和可擴展性,這些措施可以幫助Java在云原生環境中更好地發展
作者:京東科技 徐擁
來源:京東云開發者社區
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/555196.html
標籤:其他
下一篇:返回列表
