应用级服务发现地址迁移规则说明

本文规定了地址迁移过程中使用的规则体信息。用户可以根据自己的需要自定义迁移规则。

状态模型

在 Dubbo 3 之前,地址注册模型是以接口级粒度注册到注册中心的,而 Dubbo 3 的新应用级注册模型是以应用级粒度注册到注册中心的。注册中心的实现几乎不同,这导致无法将从接口级注册模型获取的调用器与从应用级注册模型获取的调用器合并。为了帮助用户从接口级迁移到应用级,Dubbo 3 设计了迁移机制,该机制基于三种状态的切换,实现了实际调用中地址模型的切换。

//imgs/v3/migration/migration-1.png

目前有三种状态,FORCE_INTERFACE(强制接口级)、APPLICATION_FIRST(应用级优先)、FORCE_APPLICATION(强制应用级)。

FORCE_INTERFACE:仅在兼容模式下启用接口级服务发现的注册中心逻辑,100% 的调用流量遵循原有流程 APPLICATION_FIRST:启用接口级和应用级双订阅,并在运行时根据阈值和灰度流量比例动态确定调用流量方向 FORCE_APPLICATION:仅在新模式下启用应用级服务发现的注册中心逻辑,100% 的调用流量都到应用级订阅的地址

规则体说明

规则以 yaml 格式配置,具体配置如下

key: consumer application name (required)
step: state name (required)
threshold: decision threshold (default 1.0)
proportion: grayscale ratio (default 100)
delay: delay decision time (default 0)
force: force switching (default false)
interfaces: interface granularity configuration (optional)
  - serviceKey: interface name (interface + : + version number) (required)
    threshold: decision threshold
    proportion: grayscale ratio
    delay: delay decision time
    force: force switch
    step: state name (required)
  - serviceKey: interface name (interface + : + version number)
    step: state name
applications: application granular configuration (optional)
  - serviceKey: application name (consumed upstream application name) (required)
    threshold: decision threshold
    proportion: grayscale ratio
    delay: delay decision time
    force: force switch
    step: state name (required)
  • key:消费者应用名称
  • step:状态名称(FORCE_INTERFACE、APPLICATION_FIRST、FORCE_APPLICATION)
  • threshold:决策阈值(浮点数,具体含义请参考下文)
  • proportion:灰度比例(0 到 100,决定调用次数的比例)
  • delay:延迟决策时间(延迟决策时间,实际等待时间为延迟时间的 1~2 倍,取决于注册中心第一次通知的时间,对于当前 Dubbo 注册中心实现二次配置项保持 0)
  • force:强制切换(对于 FORCE_INTERFACE、FORCE_APPLICATION 是否直接切换而不考虑决策,这可能会导致没有地址调用失败)
  • interfaces:接口粒度配置

参考配置示例如下

key: demo-consumer
step: APPLICATION_FIRST
threshold: 1.0
proportion: 60
delay: 0
force: false
interfaces:
  - serviceKey: DemoService: 1.0.0
    threshold: 0.5
    proportion: 30
    delay: 0
    force: true
    step: APPLICATION_FIRST
  - serviceKey: GreetingService: 1.0.0
    step: FORCE_APPLICATION

配置方法说明

  • Key:消费者应用名称 + “.migration”
  • Group:DUBBO_SERVICEDISCOVERY_MIGRATION

配置项内容参考上一节

程序启动时,会将此配置作为最高优先级的启动项拉取。当配置项为启动项时,不会进行任何检查操作,直接根据状态信息达到最终状态。程序运行过程中收到新的配置项时,会进行迁移操作,过程中会对配置信息进行校验,如果校验失败,则会回滚到迁移前的状态。迁移是以接口粒度进行的,也就是说,如果一个应用有 10 个接口,其中 8 个迁移成功,2 个失败,那么在最终状态下,8 个成功迁移的接口会执行新的行为,而 2 个失败的接口仍然是旧状态。如果需要重新触发迁移,可以通过重新交付规则来实现。

注意:如果程序在迁移过程中因校验失败而回滚,由于程序没有写回配置项的行为,此时如果重启程序,程序会直接按照新的行为进行初始化,而不会进行校验。

2. 启动参数配置

  • 配置项名称:dubbo.application.service-discovery.migration
  • 允许值范围:FORCE_INTERFACE、APPLICATION_FIRST、FORCE_APPLICATION

此配置项可以通过环境变量或配置中心传入,优先级低于启动时的配置文件,即当配置中心不存在配置文件时,会读取此配置项作为启动状态。

3. 本地文件配置

配置项名称默认值说明
dubbo.migration.filedubbo-migration.yaml本地配置文件路径
dubbo.application.migration.delay60000配置文件延迟生效时间(毫秒)

配置文件中的格式与上述规则一致

本地文件配置方式本质上是一种延迟配置下发的方式,本地文件不会影响默认的启动方式,当达到延迟时间后,会触发一次与本地文件内容一致的下发通知,这里的延迟时间与规则体中的delay字段无关。本地文件配置方式可以保证启动时以默认行为初始化,当达到延迟时间后,触发迁移操作,并进行相应的校验,避免启动时即处于最终态。

决策说明

1. 阈值检测

阈值机制的设计是为了在流量切换之前检查地址数量。如果将应用级别的可用地址数量与接口级别的可用地址数量进行比较,如果未达到阈值,则检查失败。

核心代码如下

if (((float) newAddressSize / (float) oldAddressSize) >= threshold) {
    return true;
}
return false;

同时,MigrationAddressComparator 也是一个 SPI 扩展点,用户可以自行扩展,所有检查的结果取交集。

2. 灰度

灰度功能仅在应用级优先状态下生效。此功能允许用户确定调用新模式应用级注册中心地址的比例。灰度生效的前提是满足阈值检测。在应用级优先状态下,如果阈值检测通过,则 currentAvailableInvoker 会切换为应用级地址对应的 invoker;如果检测失败,currentAvailableInvoker 仍然是原先接口级地址对应的 invoker。

流程图如下:检测阶段 //imgs/v3/migration/migration-2.png 调用阶段 //imgs/v3/migration/migration-3.png

核心代码如下

// currentAvailableInvoker is based on MigrationAddressComparator's result
if (currentAvailableInvoker != null) {
    if (step == APPLICATION_FIRST) {
        // call ratio calculation based on random value
        if (ThreadLocalRandom. current(). nextDouble(100) > promotion) {
            return invoker.invoke(invocation);
        }
    }
    return currentAvailableInvoker.invoke(invocation);
}

切换流程说明

地址迁移的过程涉及到三种状态的切换,为了保证平滑迁移,需要支持 6 种切换路径,可以概括为从强制接口级、强制应用级切换到应用级优先;应用级优先切换到强制接口级、强制应用级切换;还有强制接口级与强制应用级之间互相切换。同一接口的切换流程始终是同步的,如果上一个规则还未处理完成,就收到了新的规则,则会进行等待。

1. 切换到应用级优先

从强制接口级、强制应用级切换到应用级优先,本质上是从单订阅切换到双订阅的过程,保留原有的订阅,并创建另一个订阅。在此切换模式下,规则体中配置的延迟配置不会生效,即创建完订阅后会立即进行阈值检测,并决策选择某一组订阅进行实际的优先调用。由于应用级优先模式支持运行时动态阈值检测,因此对于部分注册中心启动失败,未获取到全部地址的场景,会在所有地址都通知到位后,重新计算阈值并进行切换。应用级优先模式下的动态切换是基于服务目录(Directory)的地址监听器实现的。 //imgs/v3/migration/migration-4.png

2. 应用级优先切换到强制

从应用级优先切换到强制接口级、强制应用级的过程,会对双订阅的地址进行校验,如果满足则销毁另一个订阅,如果不满足则回滚到原先的应用级优先状态。如果用户希望切换流程不进行校验直接切换,可以通过配置 force 参数实现。 //imgs/v3/migration/migration-5.png

3. 强制接口级与强制应用级之间互相切换

强制接口级与强制应用级之间互相切换,需要临时创建一个新的订阅,判断新的订阅是否达标(即计算阈值时使用新订阅的地址数量减去旧订阅的地址数量),不达标则销毁新的订阅,回滚到之前的状态。 //imgs/v3/migration/migration-6.png


上次修改时间:2023 年 1 月 2 日: 增强英文文档 (#1798) (95a9f4f6c1c)