3.2 升级至 3.3

Dubbo 3.3 升级与兼容性指南

对于绝大多数的用户,升级到 Dubbo 3.3.0 是完全平滑的,仅需要修改依赖包版本即可。

  1. <dependency>
  2. <groupId>org.apache.dubbo</groupId>
  3. <artifactId>dubbo</artifactId>
  4. <version>3.3.0</version>
  5. </dependency>

或者

  1. <dependency>
  2. <groupId>org.apache.dubbo</groupId>
  3. <artifactId>dubbo-spring-boot-starter</artifactId>
  4. <version>3.3.0</version>
  5. </dependency>

兼容性 CheckList

1. 默认序列化切换

Dubbo 3.3.0 版本开始默认序列化方式从 fastjson2 切换为 hessian2,对于升级到 3.3.0 的应用,Dubbo 会自动尝试采用 hessian2 进行序列化。

Q1:为什么要切换默认序列化方式?

hessian2 为 Dubbo 3.1.x 及以下版本中默认的序列化,长期的生产验证了其稳定性和兼容性,在评估了向前兼容性和长期可维护性后,Dubbo 团队决定将 hessian-lite 升级到最新 hessian4 主干版本,以支持 JDK17 和 JDK21。

升级到 Dubbo 3.3.0 以后,依赖的 hessian-lite 版本将同步升级为 4.0.x,主要包含以下修改:

  • 同步 hessian 到上游 4.0.66 版本
  • 修复 JDK17 及 JDK21 下类可见性带来的兼容性问题
  • 支持 Record、ImmutableCollections 等 JDK9+ 特性

Q2:会不会影响和低版本的 Dubbo 互通?

部分场景下可能会有影响,具体如下:

  1. Dubbo 3.3.x Consumer 与 Dubbo 3.2.x Provider 互通时默认使用 Dubbo 3.2.x 中 fastjson2 优先的策略,无兼容性问题
  2. Dubbo 3.3.x Consumer 与 Dubbo 3.1.x 及以下版本 Provider 互通时默认使用 Dubbo 3.2.x 中 fastjson2 优先的策略,无兼容性问题
  3. Dubbo 3.2.x Consumer 与 Dubbo 3.3.x Provider 互通时默认使用 Dubbo 3.3.x 中 hessian2 优先的策略,此时由于 Dubbo 3.2.x Consumer 中携带的 hessian2 为低版本的,在 JDK >= 17 的场景下可能会出现兼容性问题,建议按照 Q3 中的最佳实践进行升级。
  4. Dubbo 3.1.x 及以下版本 Consumer 与 Dubbo 3.3.x Provider 互通时默认使用 Dubbo 3.3.x 中 hessian2 优先的策略,此时由于 Dubbo 3.1.x 及以下版本 Consumer 中携带的 hessian2 为低版本的,在 JDK >= 17 的场景下可能会出现兼容性问题,建议按照 Q3 中的最佳实践进行升级。

原理可参考序列化协议升级指南一文。

Q3:升级序列化最佳实践是什么?

  1. 从 Dubbo 3.2.x 升级到 3.3.x 时,建议配置 prefer-serializationfastjson2,hessian2 保持与 3.2.x 一致,待全集群升级完毕后在删除该配置,使用 hessian2 序列化
  2. 从 Dubbo 3.1.x 及以下版本升级到 3.3.x 时,无需配置 prefer-serialization,但需要注意避免与 JDK 升级一起进行,以免出现兼容性问题

Q4:如果我仍想使用 fastjson2,怎么办?

如果你不想使用 hessian2,可以配置 prefer-serializationfastjson2 覆盖默认配置。(如 dubbo.provider.prefer-serialization=fastjson2,hessian2


2. 使用 register=false 不注册时将无法通过 QoS 手动注册

如果注册中心配置中配置了 dubbo.registry.register=false 或者指定服务配置 dubbo.provider.register=false

  1. 在 Dubbo 3.2.x 及以前版本中,默认 Dubbo 不自动注册,使用 QoS 命令(curl http://127.0.0.1:22222/online )可以实现注册
  2. 在 Dubbo 3.3.x 中,默认 Dubbo 不自动注册,使用 QoS 命令也无法注册

Q1: 为什么要做这个调整?

为了避免有的用户使用优雅上下线和隔离环境配置预期不一致,造成跨环境错误注册的情况,将 register=false 定义为永远不注册delay=-1-Ddubbo.application.manual-register=true 定义为延迟到手动注册

Q2: 实现优雅上线的最佳实践是什么?

简单来说需要完成两个配置:delay=-1-Ddubbo.application.manual-register=true

delay=-1 实现指定服务允许优雅上线:

  1. 如果需要对全部的服务都进行优雅上线,可以在 dubbo.provider.delay=-1 配置
  2. 如果只需要对部分服务进行优雅上线,可以在指定服务配置 delay=-1

-Ddubbo.application.manual-register=true 实现手动注册: 对于需要进行优雅上线的机器,配置 -Ddubbo.application.manual-register=true JVM 参数

完善启动脚本: 对于需要进行优雅上线的机器,启动脚本中在启动结束后,主动调用 QoS 命令 curl http://127.0.0.1:22222/online 进行注册

考虑因素:

  1. 全局一套代码,无论是线上环境、测试环境均对需要优雅上线的服务进行配置 delay=-1
  2. 仅对线上环境进行 -Ddubbo.application.manual-register=true 配置,测试环境不配置,保证测试环境的服务能够自动注册

3. Nacos 兼容订阅默认关闭

从 Dubbo 3.3.x 版本开始,将不再订阅 Dubbo 2.7.3 及以前版本的兼容服务名,如果仍需要订阅,请配置 -Dnacos.subscribe.legacy-name=true

Q1: 为什么要做这个调整?

在 Dubbo 2.7.3 及以前版本中,Dubbo 服务注册到 Nacos 时,订阅格式为 providers(:{interfaceName})(:{version})(:{group}),其中每个字段如果本身未空,会连带前面的 : 也一起省略,导致订阅名字不唯一,无法精确订阅。

如:

  1. 接口名:com.foo.BarService,版本:1.0.0,分组:baz,订阅名字为 providers:com.foo.BarService:1.0.0:baz
  2. 接口名:com.foo.BarService,版本:空,分组:baz,订阅名字为 providers:com.foo.BarService:baz
  3. 接口名:com.foo.BarService,版本:baz,分组:空,订阅名字为 providers:com.foo.BarService:baz

如上,2 和 3 的订阅名字是一样的,但实际上是不同的服务。

为了解决这个问题,Dubbo 2.7.4 及以后版本中,订阅名字将会变为 providers:({interfaceName}):({group}):({version}),保证订阅名字的唯一性。

如:

  1. 接口名:com.foo.BarService,版本:1.0.0,分组:baz,订阅名字为 providers:com.foo.BarService:1.0.0:baz
  2. 接口名:com.foo.BarService,版本:空,分组:baz,订阅名字为 providers:com.foo.BarService::baz
  3. 接口名:com.foo.BarService,版本:baz,分组:空,订阅名字为 providers:com.foo.BarService:baz:

4. Dubbo Spring Boot Starters 更新

在 Dubbo 3.3.x 中,Dubbo Spring Boot Starters 为了方便依赖管理,提供了更多的 Starter 依赖。

此外:为了遵循 Spring 规范的命名规范,从 3.3.0 版本开始,可观测相关 Starter 的 artifactId 从 dubbo-spring-boot-observability-starter 更名为 dubbo-observability-spring-boot-starter

Q1: Dubbo 3.3.x 版本中的 Starter 有哪些?

以下是 Dubbo 官方社区提供的 starter 列表(3.3.0+ 版本),方便在 Spring Boot 应用中快速使用:

  • dubbo-spring-boot-starter,管理 dubbo 核心依赖,用于识别 application.properties 或 application.yml 中 dubbo. 开头的配置项,扫描 @DubboService 等注解。
  • dubbo-spring-boot-starter3,管理 dubbo 核心依赖,与 dubbo-spring-boot-starter 相同,支持 spring boot 3.2 版本。
  • dubbo-nacos-spring-boot-starter,管理 nacos-client 等依赖,使用 Nacos 作为注册中心、配置中心时引入。
  • dubbo-zookeeper-spring-boot-starter,管理 zookeeper、curator 等依赖,使用 Zookeeper 作为注册中心、配置中心时引入(Zookeeper server 3.4 及以下版本使用)。
  • dubbo-zookeeper-curator5-spring-boot-starter,管理 zookeeper、curator5 等依赖,使用 Zookeeper 作为注册中心、配置中心时引入。
  • dubbo-sentinel-spring-boot-starter,管理 sentinel 等依赖,使用 Sentinel 进行限流降级时引入。
  • dubbo-seata-spring-boot-starter,管理 seata 等依赖,使用 Seata 作为分布式事务解决方案时引入。
  • dubbo-observability-spring-boot-starter,加入该依赖将自动开启 Dubbo 内置的 metrics 采集,可用于后续的 Prometheus、Grafana 等监控系统。
  • dubbo-tracing-brave-spring-boot-starter,管理 brave/zipkin、micrometer 等相关相关依赖,使用 Brave/Zipkin 作为 Tracer,将 Trace 信息 export 到 Zipkin。
  • dubbo-tracing-otel-otlp-spring-boot-starter,管理 brave/zipkin、micrometer 等相关相关依赖,使用 OpenTelemetry 作为 Tracer,将 Trace 信息 export 到 OTlp Collector。
  • dubbo-tracing-otel-zipkin-spring-boot-starter,管理 brave/zipkin、micrometer 等相关相关依赖,使用 OpenTelemetry 作为 Tracer,将 Trace 信息 export 到 Zipkin。

5. 迁移 dubbo-compiler 和 dubbo-native-plugin 到 dubbo-maven-plugin

在 3.3 版本中,Dubbo 移除了 dubbo-native-plugin,同时 dubbo-native-plugin 相关的功能都将迁移至 dubbo-maven-plugin。此外,在 dubbo-maven-plugin 中也新增了对 dubbo-compiler 的支持。

更多过于 dubbo-maven-plugin 的说明请参考配置详情

Q1:为什么要做这个迁移和调整?

  1. 为了提升用户的使用体验,后续dubbo有关maven的插件能力都将统一使用dubbo-maven-plugin来提供。方便Dubbo用户使用和接入。而不需要一个特性对应一个插件,导致用户需要依赖多个plugin。
  2. 更加有利于后续Dubbo提供maven plugin能力时的维护和特性增强。

Q2:如何迁移配置?

  1. 使用 Native Image 时,原配置为:
  1. <plugin>
  2. <groupId>org.apache.dubbo</groupId>
  3. <artifactId>dubbo-maven-plugin</artifactId>
  4. <version>${dubbo.version}</version>
  5. <configuration>
  6. <mainClass>com.example.nativedemo.NativeDemoApplication</mainClass>
  7. </configuration>
  8. <executions>
  9. <execution>
  10. <phase>process-sources</phase>
  11. <goals>
  12. <goal>dubbo-process-aot</goal>
  13. </goals>
  14. </execution>
  15. </executions>
  16. </plugin>

需要替换为:

  1. <plugin>
  2. <groupId>org.apache.dubbo</groupId>
  3. <artifactId>dubbo-maven-plugin</artifactId>
  4. <version>${dubbo.version}</version>
  5. <configuration>
  6. <mainClass>org.apache.dubbo.registry.consumer.NativeDemoConsumerRegistryApplication</mainClass>
  7. </configuration>
  8. <executions>
  9. <execution>
  10. <phase>process-sources</phase>
  11. <goals>
  12. <goal>dubbo-process-aot</goal>
  13. </goals>
  14. </execution>
  15. </executions>
  16. </plugin>

注:仅需要替换 artifactId

  1. 使用 Triple + Protobuf 时,原配置为:
  1. <build>
  2. <extensions>
  3. <extension>
  4. <groupId>kr.motd.maven</groupId>
  5. <artifactId>os-maven-plugin</artifactId>
  6. <version>1.6.1</version>
  7. </extension>
  8. </extensions>
  9. <plugins>
  10. <plugin>
  11. <groupId>org.xolstice.maven.plugins</groupId>
  12. <artifactId>protobuf-maven-plugin</artifactId>
  13. <version>0.6.1</version>
  14. <configuration>
  15. <protocArtifact>com.google.protobuf:protoc:${protoc.version}:exe:${os.detected.classifier}
  16. </protocArtifact>
  17. <pluginId>grpc-java</pluginId>
  18. <pluginArtifact>io.grpc:protoc-gen-grpc-java:${grpc.version}:exe:${os.detected.classifier}
  19. </pluginArtifact>
  20. <protocPlugins>
  21. <protocPlugin>
  22. <id>dubbo</id>
  23. <groupId>org.apache.dubbo</groupId>
  24. <artifactId>dubbo-compiler</artifactId>
  25. <version>${dubbo.compiler.version}</version>
  26. <mainClass>org.apache.dubbo.gen.tri.Dubbo3TripleGenerator</mainClass>
  27. </protocPlugin>
  28. </protocPlugins>
  29. </configuration>
  30. <executions>
  31. <execution>
  32. <goals>
  33. <goal>compile</goal>
  34. </goals>
  35. </execution>
  36. </executions>
  37. </plugin>
  38. </plugins>
  39. </build>

可以直接替换为:

  1. <build>
  2. <plugins>
  3. <plugin>
  4. <groupId>org.apache.dubbo</groupId>
  5. <artifactId>dubbo-maven-plugin</artifactId>
  6. <version>${dubbo.version}</version>
  7. <executions>
  8. <execution>
  9. <goals>
  10. <goal>compile</goal>
  11. </goals>
  12. </execution>
  13. </executions>
  14. </plugin>
  15. </plugins>
  16. </build>

注:无需引入 os-maven-pluginprotobuf-maven-plugin,仅需要引入 dubbo-maven-plugin 即可。


6. 移除原 REST 协议支持

在 Dubbo 3.3.x 中,Triple 协议支持了 Provider 侧原生 REST 协议的所有特性,同时移除了原 REST 协议实现的支持。

  1. 如果仅使用 REST 协议作为服务提供者,请修改协议名字为 tri,使用方式无需改变,详见 Triple 3.3新特性Triple REST 用户手册
  2. 如果需要使用 REST 协议作为服务消费者,可以添加以下依赖提供能力兼容
  1. <dependency>
  2. <groupId>org.apache.dubbo.extensions</groupId>
  3. <artifactId>dubbo-rpc-rest</artifactId>
  4. <version>3.3.0</version>
  5. </dependency>

7. JDK 序列化

由于 JDK 原生序列化中,如果不手动添加配置,存在大量的反序列化漏洞,为了提升 Dubbo 的安全性,Dubbo 3.3.x 版本中默认不支持 JDK 序列化。

如果需要使用 JDK 序列化,可以添加以下依赖提供能力兼容,但请注意,这可能会引入安全风险

  1. <dependency>
  2. <groupId>org.apache.dubbo.extensions</groupId>
  3. <artifactId>dubbo-serialization-jdk</artifactId>
  4. <version>3.3.0</version>
  5. </dependency>

8. 传递依赖变更

在 Dubbo 3.3.x 中,默认不再传递以下依赖,如有需要请按需引入:

  1. <dependency>
  2. <groupId>org.springframework</groupId>
  3. <artifactId>spring-core</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>org.springframework</groupId>
  7. <artifactId>spring-beans</artifactId>
  8. </dependency>
  9. <dependency>
  10. <groupId>org.springframework</groupId>
  11. <artifactId>spring-context</artifactId>
  12. </dependency>
  13. <dependency>
  14. <groupId>com.alibaba.spring</groupId>
  15. <artifactId>spring-context-support</artifactId>
  16. </dependency>

同时,新增传递以下依赖:

  1. <dependency>
  2. <groupId>com.google.protobuf</groupId>
  3. <artifactId>protobuf-java</artifactId>
  4. </dependency>
  5. <dependency>
  6. <groupId>com.google.protobuf</groupId>
  7. <artifactId>protobuf-java-util</artifactId>
  8. </dependency>

注:Dubbo 从 3.3.x 开始不再依赖 com.alibaba.spring:spring-context-support 实现自身能力,如果需要请自行引入。


9. Zookeeper 3.4 支持移除

由于 Zookeeper 3.4.x 已经 EOL 4 年多了,为了降低 Dubbo 的维护成本,Dubbo 3.3.x 版本中移除了对 Zookeeper 3.4.x 的支持,请迁移 Curator (如有)到 5.x 版本。

最后修改 September 13, 2024: Refactor website structure (#2860) (1a4b998f54b)