dubbo3 新特性
1. Dubbo3 应用级服务发现设计
- 显著降低服务发现过程的资源消耗,包括提升注册中心容量上限、降低消费端地址解析资源占用等,使得 Dubbo3 框架能够支持更大规模集群的服务治理,实现无限水平扩容。
- 适配底层基础设施服务发现模型,如 Kubernetes、Service Mesh 等。
官网纤细介绍: https://cn.dubbo.apache.org/zh-cn/overview/reference/proposals/service-discovery/
2. 彻底解决递归初始化问题
dubbo2.x 每次ReferenceBean初始化完成后都执行ReferenceBean#prepareDubboConfigBeans
在Dubbo3.0中有一个关于这块内容的优化,主要是为了修复功能缺陷,而不是为了解决性问题,这个性能问题其实也只有在ReferenceBean数量足够多的时候才会出现。但按照这个思路,应该是可以顺便解决性能问题的。 Improve dubbo config beans and bootstrap initialization、Dubbo3 Spring相关优化
3. 全新通信协议Triple
全新通信协议Triple 让跨语言RPC迈了一大步,支持点对点调用、stream 流式调用。写proto IDL 文件可生成各类客户端代码,完全兼容grpc
dubbo3 变更内容
1. 默认使用fastjson2序列化
dubbo2.x 默认使用的是hessian2序列化方式, dubbo3.2 中默认使用的是fastjson2序列化,
原因:可能是认为fastjson2性能比较高,
官方序列化协议变更方案: 序列化协议升级
2. Protostuff序列化的maven坐标变更
Protostuff序列化的maven坐标变更, 放在了单独的github 仓库,
https://github.com/apache/dubbo-spi-extensions/tree/master/dubbo-serialization-extensions
<dependency>
<groupId>org.apache.dubbo.extensions</groupId>
<artifactId>dubbo-serialization-protostuff</artifactId>
<version>1.0.1</version>
</dependency>
3. Nacos Group 对齐(应用级服务发现)
- 在 Dubbo 2.7.x 中,配置在 Nacos Registry URL 上的 group 值是对齐 Nacos 注册中心中的 group 分组的。(group 可以当成类似 namespace 的软隔离)
- 在 Dubbo 3.0.x 中,配置在 Nacos Registry URL 上的 group 默认不使用,全部使用 DEFAULT_GROUP。(group 不再提供隔离功能)
- 在 Dubbo 3.1.x 中,配置在 Nacos Registry URL 上的 group 值将会重新对齐 Nacos 注册中心中的 group 分组的。
- 注意事项:
- 请检查注册中心 URL 上是否已经配置了 group 属性,如果是的话需要检查服务端和消费端的 group 是否都一致,如果不一致请修改为一致
- 如果不希望 group 重新对齐到 Nacos 注册中心中的 group 分组,可以配置
dubbo.nacos-service-discovery.use-default-group=false
全局属性值忽略该功能
4. 序列化检查模式(重要!!!)
在 Dubbo 3.2.0 版本中,Dubbo 将默认开启序列化白名单的强校验,以提升 Dubbo 的安全性,避免远程命令执行的问题。 对于一些使用了泛型等可能存在扫描不全或者是服务规模较大的用户,
建议添加 -Ddubbo.application.serialize-check-status=WARN
配置。 观察一段时间后(通过日志、QoS 命令),如果没有触发安全告警,则可以配置强校验模式。
关于自定义白名单的配置,可以参考官网的dubbo类检查机制
Q1:为什么要开启序列化白名单的强校验?
由于 Java 本身机制的问题,Dubbo 支持的非 IDL 序列化天然允许访问任意类,这将可能导致远程命令执行(RCE)风险。
Q2:升级到 3.2 的最佳实践是什么?
建议所有用户在升级 Dubbo 3.2.0 版本前添加 -Ddubbo.application.serialize-check-status=WARN
配置以保证最佳的兼容性。否则可能导致线上数据异常的情况!
5. 默认关闭推空保护
Dubbo 3.2.0 版本开始默认关闭推空保护,即使注册中心推送空地址,Dubbo 也将不会保留最后一批 provider 信息。 如果需要开启推空保护,可以配置 dubbo.application.enable-empty-protection=true
。
Q1:关闭推空保护对我有什么影响?
在绝大部分场景下没有影响。 推空保护的目的是在注册中心出现故障并且主动推送空地址的时候,Dubbo 保留最后一批 provider 信息,以保证服务可用。 但是在大多数注册中心出现故障的时候,注册中心也不会推送空地址,只有一些特殊情况才会出现。 但如果开启推空保护,将对 Dubbo 的 Fallback 逻辑、心跳逻辑等造成较大的影响,给开发使用 Dubbo 带来困扰。
Q2:我想开启推空保护,怎么办?
如果在生产上为了高可用,需要开启推空保护,可以配置 dubbo.application.enable-empty-protection=true
。 目前已知开启推空保护会导致服务端应用从 2.6.x、2.7.x 等仅支持接口级服务发现的版本升级到 3.x 之后回滚到原来版本出现异常,极端场景下会导致服务调用失败。 此外,开启推空保护后在服务端地址真的为空的时候出现较多的心跳异常、日志异常等。
升级步骤
如果使用 Nacos 作为注册中心,由于 Nacos 特性支持的原因,在升级到 Dubbo 3.x 之前需要将 Nacos Server 升级到 2.x(参考文档https://nacos.io/zh-cn/docs/v2/upgrading/2.0.0-upgrading.html
),然后再将应用的 Nacos Client 也对应升级。如果使用 Zookeeper 注册中心则不需要处理。
1. 升级jar依赖
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo</artifactId>
<version>3.2.4</version>
<exclusions>
<exclusion>
<groupId>com.alibaba.fastjson2</groupId>
<artifactId>fastjson2</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.apache.dubbo</groupId>
<artifactId>dubbo-spring-boot-starter</artifactId>
<version>3.2.4</version>
</dependency>
2. 服务端配置
dubbo.application.register-mode
服务端提供者服务的注册模式 可选值有
instance
只注册实例应用级all
接口级+应用级均注册interface
只注册接口级
升级到3.x之后在不修改配置的情况下默认是all
配置 开启接口级
+应用级
注册
3. 消费端/客户端
服务有注册模式 那么消费端肯定也有服务订阅发现模式设置
dubbo.application.service-discovery.migration
消费端订阅模式可选值有
APPLICATION_FIRST
双订阅 即接口模式/应用级模式 智能决策 一般用于2.7.x与3.x 升级中 共存阶段 也是3.x版本默认的订阅模式, 运行时根据阈值和灰度流量比例动态决定调用流量走向FORCE_APPLICATION
仅应用级订阅模式FORCE_INTERFACE
仅接口级订阅模式
关于兼容这一步如果项目升级的时候没有用户使用 不做兼容性升级也没问题,这里主要是介绍保障逐步把2.7.x版本升级到3.x 而不是全部停机后重新部署。
对于双订阅的场景,消费端虽然可同时持有 2.x 地址与 3.x 地址,但选址过程中两份地址是完全隔离的:要么用 2.x 地址,要么用 3.x 地址,不存在两份地址混合调用的情况,应用级服务发现地址迁移规则说明。
大概操作流程如下
- 把部分Provider替换为3.x 服务端注册模式为
all
, 即应用级
+接口级
,这样2.7.x消费端也能够根据接口服务发现 - 把部分Consumer替换为3.x 消费订阅模式为
FORCE_INTERFACE
只订阅接口模式, 不采用官网推荐的APPLICATION_FIRST
混合模式原因是: 混合模式可能出现流量偏移 - 少量灰度部署, 验证Dubbo高低版本调用是否正常。没啥问题的话就可以逐步全部切换到3.x版本
- 重点: 到了这一步说明当前所有实例均为3.x版本,下次再更新的时候就把消费端订阅模式设置为
FORCE_APPLICATION
- 消费端全部设置重启后, 再把服务端注册模式设置为instance ,就完美切换到3.x版本 并且是应用级服务发现。
需要元数据中心支持
dubbo3为了做到应用级别发现, 对dubbo 接口和应用名通过元数据中心作了映射
潜在风险
-
在dubbo2和dubbo3共存期间, 注册的元数据信息会增长, 双注册带来的资源消耗
双注册不可避免的会带来额外的注册中心存储压力,但考虑到应用级地址发现模型的数据量在存储方面的极大优势,即使对于一些超大规模集群的用户而言,新增的数据量也并不会带来存储问题。总体来说,对于一个普通集群而言,数据增长可控制在之前数据总量的 1/100 ~ 1/1000
以一个中等规模的集群实例来说: 2000 实例、50个应用(500 个 Dubbo 接口,平均每个应用 10 个接口)。
假设每个接口级 URL 地址平均大小为 5kb,每个应用级 URL 平均大小为 0.5kb- 老的接口级地址量:2000 * 500 * 5kb ≈ 4.8G
- 新的应用级地址量:2000 * 50 * 0.5kb ≈ 48M
双注册后仅仅增加了 48M 的数据量。
-
在跨版本升级的过程中,存在的风险点从大到小分别有:直接修改 Dubbo 源码 -> 基于 Dubbo SPI 扩展点进行扩展 -> 基于 API 或者 Spring 的使用方式
-
dubbo 2.7中也有应用级别服务发现, 要先关闭
-
对于 SPI 扩展的,除了应用级服务方向和 EventDispatcher 两个机制在 3.x 中做了破坏性的修改,在 2.7.x 中提供的绝大多数的扩展在 3.x 中也都提供。此部分需要关注的有两个方面:
- 事件总线:出于事件管理的复杂度原因,EventDispatcher 和 EventListener 在 Dubbo 3.x 的支持已经删除。如果有对应扩展机制的使用请考虑重构为对应 Dubbo 功能的扩展。
- 应用级服务发现:Dubbo 2.7 中的应用级服务发现的整体机制在 Dubbo 3.x 中已经被完整重构,功能的性能与稳定性有了很大程度上的提高。因此我们建议您不要使用 Dubbo 2.7 中的应用级服务发现机制,如果有对应的扩展可以在升级到 Dubbo 3.x 之后基于新的代码重新验证实现(绝大多数应用级服务发现的 API 是向前兼容的)。
-
dubbo服务的URL不再注册
使用dubbo3的注册方式后, 不存在dubbo服务的URL, 而是通过点对点拉取
-
dubbo3 consumer列表不存在, 不方便观察, 可能需要打开元数据中心
升级观测指标
在发布的过程中,有以下几个维度的指标可以判断升级是否出现问题。
- 机器的 CPU、内存使用情况
- 接口请求成功率
- 接口请求 RT
- 日志的报错信息
- 自定义扩展行为是否符合预期
参考文档:
官网文档 dubbo 2.x 升级至 3.x
相关链接
dubbo3升级案例