Dubbo 正式支持 Spring 6 & Spring Boot 3
背景
Spring Framework 6.0 于 11 月 16 日正式發(fā)布 GA 版本,Spring Boot 3.0 也于 11 月 25 日正式發(fā)布 GA 版本,并且 Spring 6 & SpringBoot 3 最低支持 JDK17,意味著如果升級使用 Spring 6 & Spring Boot 3 時就必須需要升級使用 JDK17。
然而 Java 8 目前是國內(nèi)主流生產(chǎn)環(huán)境 Java 版本之一。雖然近幾年陸續(xù)發(fā)布了 Java 11、Java 17 官方 LTS 版本,但是大部分開發(fā)者依然本著 “你發(fā)任你發(fā),我用 Java8” 的看法看待 JDK 的升級。不過 Java 17 版本在性能上確實做了大量的優(yōu)化特別是 ZGC 的發(fā)布,促進了國內(nèi)不少企業(yè)升級到 Java 17。
而 Spring 框架在 Java 生態(tài)中的重要程度不言而喻,我們相信在 Spring 這波“最低支持 JDK17” 推動下,Spring Framework 6.0 & Spring Boot 3.0 一定會在不久的將來被大家接受,并成為主流技術(shù)棧。
Dubbo 社區(qū)非常重視 Spring 社區(qū)的更新迭代,總會積極支持適配,這點在最近 Spring 6.0 和 Spring Boot 3.0 發(fā)布中同樣得到了驗證。Dubbo 社區(qū)早在Spring 6.0.0-RC4 和 Spring Boot 3.0.0-RC2 時已經(jīng)做好了大致的兼容適配,但是為了保證 Dubbo 能夠完全適配 Spring 6 和 Spring Boot 3.0 的正式版,我們一直等到 Spring Boot 3.0 GA 后,才選擇宣布這個令人高興的事情。
為什么要升級到 Spring 6.0 & Spring Boot 3.0
首先是,升級到 Spring 6.0 & Spring Boot 3.0 將獲得未來很長年限的由官方提供的免費技術(shù)支撐。Spring 6 和 Spring Boot 3 是 Spring 下一代技術(shù)框架基石,盡管官方當(dāng)前同時維護了 Spring 5.3 和 Spring Boot 2.6.x 和 Spring Boot 2.7.x,但它們最終都會在 2025 年和 2026 年結(jié)束其 OSS support(Open Source Software Support)。
其次是,您將在新一代框架中獲得大量新特新,這些新特性都可以在 Spring Boot 3.0 Release Notes(
https://github.com/spring-projects/spring-boot/wiki/Spring-Boot-3.0-Release-Notes) 和 What's New in Spring Framework 6.x(https://github.com/spring-projects/spring-framework/wiki/What's-New-in-Spring-Framework-6.x) 中獲得。
最后是,Spring 6.x 和 Spring Boot 3.x 將會最廣泛的支持 JDK 17-29,需要額外說明的是 JDK17 作為當(dāng)前最新的 LTS 版本,它提供了一組累積的最新語言、API 和 JVM 增強功能,使其成為更具吸引力的編譯版本的升級,這也是為什么最低支持 JDK17 的原因。
Dubbo 支持 Spring 6 & Spring Boot 3
現(xiàn)在很高興向大家宣布,Dubbo 已經(jīng)開始兼容 Spring 6 & Spring Boot 3,所以當(dāng)前 Dubbo 3.2.0-beta.2 版本可以同時兼容支持 Spring Boot 1.x、2.x、3.x。您現(xiàn)在可以使用dubbo-3.2.0-beta.2版本體驗其兼容性。
<dependency>
?<groupId>org.apache.dubbo</groupId>
?<artifactId>dubbo-spring-boot-starter</artifactId>
?<version>3.2.0-beta.2</version></dependency>
更多關(guān)于 Spring Boot 3.0 集成 Dubbo 使用示例可參見 apache/dubbo-sample:
https://github.com/apache/dubbo-samples/tree/master/1-basic
升級總結(jié)
我們根據(jù) Dubbo 兼容適配 Spring 6 & Spring Boot 3 過程中總結(jié)的經(jīng)驗整理如下,其他組件維護者也可以參考以下經(jīng)驗進行適配或者升級,更早適配升級到最新版本:
Jakarta EE
Jakarta EE 9 將所有 API 包名從javax.*命名空間變更到了jakarta.*。而造成這一變化的原因是 Oracle 拒絕交出相關(guān)權(quán)益,詳情可以查看:
https://www.oschina.net/news/106465/oracle-killed-java-ee。
因為 Jakarta EE 的遷移,對于 Web Apps,確保升級使用 Tomcat 10, Jetty 11, or Undertow 2.2.19。
以下列出了一系列工具可以幫助你完成這部分的遷移:
OpenRewrite recipes.
The Spring Boot Migrator project.
Migration support in IntelliJ IDEA.
移除 META-INF/spring.factories 文件對 Auto-configuration 的支持
Spring Boot 3.0 移除了META-INF/spring.factories文件對 Auto-configuration 的支持,為了兼容性,SpringBoot 2.7.x 是最后一個支持的版本。
適配支持按照下面兩個步驟即可完成。
Step1: [可選] 使用?@AutoConfiguration?注解代替 [@Configuration(proxyBeanMethods ](/Configuration(proxyBeanMethods ) = false)
@AutoConfiguration 注解是 SpringBoot 2.7 中的新引入的注解,旨在專門標識 Auto-configuraton class name。
依然使用@Configuration注解標識自動適配類也是可以的,Dubbo 正是基于這個便利點完美支持了 Spring Boot 1.x、2.x、3.x 所有版本。
Step2: 使用 AutoConfiguration.imports 文件代替 META-INF/spring.factories 文件
Spring Boot 2.7 是最后一個依然兼容使用 spring.factories 的版本,SpringBoot 3 以后不再兼容,此時您應(yīng)該使用
META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports文件替換。
在該文件列舉你所有的 configuration classes,每行一個 class name,例如:
com.mycorp.libx.autoconfigure.LibXAutoConfigurationcom.mycorp.libx.autoconfigure.LibXWebAutoConfiguration
為了對齊 ISO-8601,使用 yyyy-MM-dd'T'HH:mm:ss.SSSXXX 作為默認日志日期格式
原來默認日志日期格式:yyyy-MM-dd HH:mm:ss.SSS 當(dāng)前默認日志日期格式:yyyy-MM-dd'T'HH:mm:ss.SSSXXX。
原來的默認日志日期格式不具有 timezone / offset 信息。
yyyy-MM-dd'T'HH:mm:ss.SSSXXX >>> e.g.: 2014-12-03T10:06:04.646+08:00
移除 YamlJsonParser
Spring Boot 官方測試發(fā)現(xiàn)YamlJsonParser并不能很好的解析 JSON,Spring Boot 3 決定不再支持使用它來作為解析 JSON 的備選。
YamlJsonParser 封裝的是 snakeyaml。
Spring Boot 3 解析 JSON 的解析器使用優(yōu)先級如下:
1)JacksonJsonParser
2)GsonJsonParser
3)BasicJsonParser
移除 spring.session.store-type 配置鍵
移除了spring.session.store-type配置項,當(dāng)存在多個可用存儲庫,將會按照 Redis,JDBC,Hazelcast,Mongo 順序使用。
更新 spring data 配置鍵使其清楚地反應(yīng)該配置鍵是否依賴 Spring Data
如果存儲庫(redis、mongo 等)相關(guān)的配置鍵不依賴 Spring Data 存在,則只需要 spring 前綴,否則需要使用 spring.data 前綴。
舉例說明:
spring.redis.host >> spring.data.redis.hostspring.redis.port >> spring.data.redis.portspring.data.cassandra.port >> spring.cassandra.port
重構(gòu) HttpMethod 枚舉為類
根據(jù)最新的rfc2616,HTTP Method 已經(jīng)屬于不可枚舉屬性,所以重構(gòu) HttpMethod enum 類為 class 類。
除了我們熟知的 GET, HEAD, PUT, POST 等方法,現(xiàn)在還存在了可擴展方法,當(dāng)前可擴展方法包含了 LOCK, COPY, 和 MOVE。這些擴展方法定義在 WebDAV。
不允許 URI 尾部斜杠匹配
Spring 6 之前,訪問 “/resources” 和 “/resources/” 都可以進入 resources()方法。
return "Hello from /resources";
}
String resources() { ? ?
Spring 6 之后,您只能通過看到的 path “/resources” 進入 mapping 方法。
如果您依然想讓“/resources/” 和 “/resources” 進入相同的 mapping 方法,可以通過其他手段,諸如“反向代理”、“Servlet/Web 過濾器”或“在控制器配置顯式重定向”。
提供基于 @HttpExchange 服務(wù)接口的 HTTP 客戶端
Spring 6 介紹了@HttpExchange 注解,基于 @HttpExchange 注解可以簡化 HTTP 遠程調(diào)用。
增強 Spring SPI 加載器 SpringFactoriesLoader 允許加載多自定義文件
Spring 6 之前,SpringFactoriesLoader 只允許加載"META-INF/spring.factories"文件內(nèi)容。
Spring 6 之后,SpringFactoriesLoader 可以加載自定義文件或文件名文件,并且可以通過鏈式編程加載多個文件。
早期兼容 JDK19 預(yù)覽版的虛擬線程(virtual threads)
可以在 Spring 6 和 Spring Boot 3 中使用虛擬線程處理請求來提前體驗。
這部分詳細說明參見:
https://spring.io/blog/2022/10/11/embracing-virtual-threads
支持 RFC 7807 Problem Details
Spring 6 以后,Spring MVC 可以使用 application/problem+json media 類型自定義 錯誤信息響應(yīng)體,像下面這樣:
{ ?"type": "https://example.org/problems/unknown-project", ?"title": "Unknown project", ?"status": 404, ?"detail": "No project found for id 'spring-unknown'", ?"instance": "/projects/spring-unknown"}
展望
在云原生時代,Java 的跨平臺特性,已經(jīng)不算是其亮眼特性了,而其 Jar 包體積大、啟動慢、占用內(nèi)存多、需要另裝 JVM 是 Java 應(yīng)用的痛點問題。
而通過使用 GraalVM 可以很好的解決這些問題。并且通過 GraalVM 的 AOT(Ahead-Of-Time)可以將應(yīng)用編譯成單獨可執(zhí)行文件并直接運行。
未來 Dubbo 將會積極地在 Native 方面做一些工作以此能夠使應(yīng)用程序達到下面的目標
支持 Spring & Spring Boot native-image
較小的本地應(yīng)用程序和容器鏡像占用空間
快速啟動,快速啟動(幾十毫秒)
低內(nèi)存消耗,減少 RSS(駐留集大?。?,低內(nèi)存有助于優(yōu)化需要多個容器的微服務(wù)架構(gòu)部署中的容器密度
快速的第一請求響應(yīng),避免 Hotspot 的預(yù)熱問題