双注册双订阅模式

双注册双订阅模式,第1张

注册订阅模式

双注册双订阅表示一个Provider应用可以将自身的实例信息注册到多个注册中心上,一个Consumer应用可以订阅到多个注册中心上的服务实例信息。

如图所示,Provider可以把自身的服务实例信息注册到Nacos和Eureka集群上,Consumer发起服务订阅的时候可以从Nacos和Eureka上订阅服务。

1. 双注册双订阅模式分析

Spring Cloud自身的编程模型是支持双注册双订阅模式的。在服务注册侧,Spring Cloud各个注册中心都有AutoServiceRegistration的实现类,比如,NacosAutoServiceRegistration和EurekaAutoServiceRegistration实现在类内部完成服务的注册。这些AutoServiceRegistration的实现类都实现了 Lifecycle接口,在start过程中完成服务注册 *** 作。

在服务订阅侧,DiscoveryClient 统一了Spring Cloud服务发现的 *** 作。其中,CompositeDiscoveryClient是一个特殊的DiscoveryClient实现:

package org.springframework.cloud.client.discovery.composite;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.linkedHashSet;
import java.util.List;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.core.annotation.AnnotationAwareOrderComparator;

public class CompositeDiscoveryClient implements DiscoveryClient {
    private final List discoveryClients;

    public CompositeDiscoveryClient(List discoveryClients) {
        AnnotationAwareOrderComparator.sort(discoveryClients);
        this.discoveryClients = discoveryClients;
    }

    public String description() {
        return "Composite Discovery Client";
    }

    public List getInstances(String serviceId) {
        if (this.discoveryClients != null) {
            Iterator var2 = this.discoveryClients.iterator();

            while(var2.hasNext()) {
                DiscoveryClient discoveryClient = (DiscoveryClient)var2.next();
                List instances = discoveryClient.getInstances(serviceId);
                if (instances != null && !instances.isEmpty()) {
                    return instances;
                }
            }
        }

        return Collections.emptyList();
    }

    public List getServices() {
        linkedHashSet services = new linkedHashSet();
        if (this.discoveryClients != null) {
            Iterator var2 = this.discoveryClients.iterator();

            while(var2.hasNext()) {
                DiscoveryClient discoveryClient = (DiscoveryClient)var2.next();
                List serviceForClient = discoveryClient.getServices();
                if (serviceForClient != null) {
                    services.addAll(serviceForClient);
                }
            }
        }

        return new ArrayList(services);
    }

    public List getDiscoveryClients() {
        return this.discoveryClients;
    }
}

在 getInstances 方法中,会聚合所有的 DiscoveryClient 实现类找到的服务名,也会遍历每个DiscoveryClient查询服务名对应的实例信息。

下面在一个应用里分别加上 Nacos (com.alibaba.cloud:spring-cloud-starter-alibaba-nacos-discovery)和 Eureka(org.springframework.cloud:spring-cloud-starter-netfix-eureka-client)依赖,用来完成双注册双订阅。

应用启动后,会出现以下报错信息:

***************************
APPLICATION FAILED TO START
***************************

Description:

Field autoServiceRegistration in org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration required a single bean, but 2 were found:
  - nacosAutoServiceRegistration: defined by method 'nacosAutoServiceRegistration' in class path resource [com/alibaba/cloud/nacos/registry/NacosServiceRegistryAutoConfiguration.class]
  - eurekaAutoServiceRegistration: defined by method 'eurekaAutoServiceRegistration' in class path resource [org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration.class]


Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

从这个报错信息可以很明显地看出,ServiceRegistryAutoConfiguration 自动化配置类的内部类ServiceRegistryEndpointConfiguration内部依赖一个RegistrationBean,但是在Nacos和Eureka依赖内部分别会构造 NacosRegistration 和EurekaRegistration,这样会出现 ServiceRegistry-EndpointConfiguration 并不知道要注入哪个 Registration Bean 的问题。同理,AutoService-RegistrationAutoConfiguration内部的AutoServiceRegistration Bean也会引起一样的问题。

为了解决这个问题,可以在配置文件里过滤这两个自动化配置类:

spring.autoconfigure.exclude=org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration,org.springframework.cloud.client.serviceregistry.AutoServiceRegistrationAutoConfiguration

加上该配置之后,还需要通过@EnableConfigurationProperties 注解让AutoServiceRegistration-Properties 配置类生效。这是因为所有的AutoServiceRegistration 实现类在构造过程中都需要这个配置类Bean。

有了这两个条件之后,即可享受双注册双订阅模式。

2. 案例:使用双注册双订阅模式将Eureka注册中心迁移到Nacos注册中心

假设某公司原先使用 Eureka 作为注册中心,Nacos 开源之后,该公司想把Eureka替换成Nacos注册中心,要求在这个过程中对客户没有任何影响,也不能造成业务损失。

对于这个场景,可以使用双注册双订阅方案来完成任务。如图所示,这是一个3个阶段的过程图。

第1阶段:Eureka作为注册中心,Provider完成服务注册,Consumer完成服务发现。

第2阶段:双注册双订阅的核心阶段,该阶段内部包括以下4个 *** 作。

上线新的Provider(拥有双注册能力),这时Eureka 注册中心的Provider有两个实例。下线旧的 Provider,下线之后由于新 Provider 也会注册到 Eureka 上,这时旧的Consumer可以找到新Provider的实例。上线新的 Consumer(拥有双订阅能力),新 Consumer 可以订阅 Nacos 和Eureka 集群的服务实例,这时可以订阅到Nacos上的服务实例。下线旧的Consumer。

第3阶段:Eureka下线,使用Nacos替换Eureka作为新的注册中心,Provider和Consumer的服务注册和服务发现 *** 作只与Nacos交互。

本文由博客一文多发平台 OpenWrite 发布!

欢迎分享,转载请注明来源:内存溢出

原文地址: https://www.outofmemory.cn/zaji/5712532.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-12-18
下一篇 2022-12-17

发表评论

登录后才能评论

评论列表(0条)

保存