当前位置: 首页 > news >正文

SpringBoot通过配置切换注册中心(多注册中心nacos和eureka)

场景:
因项目需要,一个springcloud微服务工程需要同时部署到A,B两个项目使用,但A项目使用Eureka注册中心,B项目使用Nacos注册中心,现在需要通过部署时修改配置来实现多注册中心的切换。
解决思路:
如果同时引入nacos和eureka的依赖和配置,不做任何处理,会导致启动失败:

***************************
APPLICATION FAILED TO START
***************************Description:Field registration in org.springframework.cloud.client.serviceregistry.ServiceRegistryAutoConfiguration$ServiceRegistryEndpointConfiguration required a single bean, but 2 were found:- nacosRegistration: defined by method 'nacosRegistration' in class path resource [com/alibaba/cloud/nacos/registry/NacosServiceRegistryAutoConfiguration.class]- eurekaRegistration: defined in BeanDefinition defined in class path resource [org/springframework/cloud/netflix/eureka/EurekaClientAutoConfiguration$RefreshableEurekaClientConfiguration.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

不难看出失败原因是单例bean找到了两个实例,那么该如何解决这个问题呢?首先想到的肯定是删除掉暂时不需要使用的实例(如使用eureka注册中心则删掉引入pom的nacos依赖),这样做是没有问题的,但是维护成本比较高。能不能从springboot自动装配原理入手,找到更便捷的方法呢?接着看:
我们都知道SpringBoot的启动类的@SpringBootApplication是一个组合注解,它里面的@EnableAutoConfiguration会引入AutoConfigurationImportSelector.class
在这里插入图片描述
在这里插入图片描述
从这个类的方法getAutoConfigurationEntry()一层一层点进去看,

SpringFactoriesLoader.loadFactories()会去检索META-INF/spring.factories文件。

protected List<AutoConfigurationImportFilter> getAutoConfigurationImportFilters() {return SpringFactoriesLoader.loadFactories(AutoConfigurationImportFilter.class, this.beanClassLoader);}

那么思路就比较清晰了,我们可以通过实现AutoConfigurationImportFilter接口,将自己的过滤逻辑写在实现类中,就可以实现自定义的自动装配过滤器了。
上代码:
通过把1、2、3的代码放到一个starter中,然后在具体的项目中引用这个starter,配置文件中添加4的配置就可以切换了,当然具体nacos和eureka在yml中的配置还是分开写,只需指定用那个配置就行
1.过滤器

package com.demo.business;import com.demo.business.constants.RegistrationCenterConstants;
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.AutoConfigurationImportFilter;
import org.springframework.boot.autoconfigure.AutoConfigurationMetadata;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;public class EngineAutoConfigurationImportFilter implements AutoConfigurationImportFilter, EnvironmentAware {private Environment environment;@Overridepublic boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {//获取配置的注册中心,默认为nacosString registryType = environment.getProperty("registry.type", RegistrationCenterConstants.NACOS);boolean[] match = new boolean[autoConfigurationClasses.length];//当自定义标识为eureka,则排除nacos的自动装配,反之同理;if (registryType.equals(RegistrationCenterConstants.EUREKA)) {for (int i = 0; i < autoConfigurationClasses.length; i++) {match[i] = !StringUtils.isNotBlank(autoConfigurationClasses[i]) ||!autoConfigurationClasses[i].equals(RegistrationCenterConstants.NACOS_SERVICE_REGISTRY_AUTO_CONFIGURATION);}} else {for (int i = 0; i < autoConfigurationClasses.length; i++) {if (StringUtils.isNotBlank(autoConfigurationClasses[i])){match[i] = !RegistrationCenterConstants.EUREKA_DISCOVERY_CLIENT_CONFIGURATION.equals(autoConfigurationClasses[i])&& !RegistrationCenterConstants.EUREKA_AUTO_CONFIGURATION_CLASSES.equals(autoConfigurationClasses[i]);}}}return match;}@Overridepublic void setEnvironment(Environment environment) {this.environment = environment;}
}或者以下这样也可以
import org.apache.commons.lang3.StringUtils;
import org.springframework.boot.autoconfigure.AutoConfigurationImportFilter;
import org.springframework.boot.autoconfigure.AutoConfigurationMetadata;
import org.springframework.context.EnvironmentAware;
import org.springframework.core.env.Environment;public class EngineAutoConfigurationImportFilter implements AutoConfigurationImportFilter, EnvironmentAware {private Environment environment;public EngineAutoConfigurationImportFilter() {}public boolean[] match(String[] autoConfigurationClasses, AutoConfigurationMetadata autoConfigurationMetadata) {String registryType = this.environment.getProperty("registry.type", "eureka");boolean[] match = new boolean[autoConfigurationClasses.length];//提取成常量String prefix = registryType.equals("nacos") ? "org.springframework.cloud.netflix.eureka" : "com.alibaba.cloud.nacos";for(int i = 0; i < autoConfigurationClasses.length; ++i) {if (StringUtils.isNotBlank(autoConfigurationClasses[i])) {match[i] = !autoConfigurationClasses[i].startsWith(prefix);}}return match;}public void setEnvironment(Environment environment) {this.environment = environment;}
}

2.常量类

package com.demo.business.constants;/*** 注册中心相关常量类*/
public class RegistrationCenterConstants {public static final String NACOS = "nacos";public static final String EUREKA = "eureka";public static final String EUREKA_AUTO_CONFIGURATION_CLASSES = "org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration";public static final String EUREKA_DISCOVERY_CLIENT_CONFIGURATION = "org.springframework.cloud.netflix.eureka.EurekaDiscoveryClientConfiguration";public static final String NACOS_SERVICE_REGISTRY_AUTO_CONFIGURATION = "com.alibaba.cloud.nacos.registry.NacosServiceRegistryAutoConfiguration";或者
public static final String NACOS_PREFIX = "com.alibaba.cloud.nacos";public static final String EUREKA_PREFIX = "org.springframework.cloud.netflix.eureka";}

3.spring.factories文件(注意路径一定要在META-INF包下)

org.springframework.boot.autoconfigure.AutoConfigurationImportFilter=\com.example.demo.business.EngineAutoConfigurationImportFilter

4.配置文件添加

registry:type: nacos

效果
通过修改配置项registry.type就可以实现eureka和nacos的切换了

相关文章:

SpringBoot通过配置切换注册中心(多注册中心nacos和eureka)

场景&#xff1a; 因项目需要&#xff0c;一个springcloud微服务工程需要同时部署到A,B两个项目使用&#xff0c;但A项目使用Eureka注册中心&#xff0c;B项目使用Nacos注册中心&#xff0c;现在需要通过部署时修改配置来实现多注册中心的切换。 解决思路&#xff1a; 如果同时…...

自动驾驶学习笔记(三)——场景设计

#Apollo开发者# 学习课程的传送门如下&#xff0c;当您也准备学习自动驾驶时&#xff0c;可以和我一同前往&#xff1a; 《自动驾驶新人之旅》免费课程—> 传送门 《2023星火培训【感知专项营】》免费课程—>传送门 文章目录 前言 场景设计平台 场景地图 场景基本…...

第 115 场 LeetCode 双周赛题解

A 上一个遍历的整数 模拟 class Solution { public:vector<int> lastVisitedIntegers(vector<string> &words) {vector<int> res;vector<int> li;for (int i 0, n words.size(); i < n;) {if (words[i] ! "prev")li.push_back(stoi…...

【IDE插件教学】华为云应用中间件系列—Redis实现(电商游戏应用)排行榜示例

云服务、API、SDK&#xff0c;调试&#xff0c;查看&#xff0c;我都行 阅读短文您可以学习到&#xff1a;应用中间件系列之Redis实现&#xff08;电商游戏应用&#xff09;排行榜示例 1 什么是DEVKIT 华为云开发者插件&#xff08;Huawei Cloud Toolkit&#xff09;&a…...

Linux:mongodb数据库源码包安装(4.4.25版本)

环境 系统&#xff1a;centos7 本机ip&#xff1a;192.168.254.1 准备的mongodb包 版本 &#xff1a; 4.4.25 全名称&#xff1a;mongodb-linux-x86_64-rhel70-4.4.25.tgz 下载源码包 Download MongoDB Community Server | MongoDBhttps://www.mongodb.com/try/downloa…...

pdf怎么合并在一起?

pdf怎么合并在一起&#xff1f;对于pdf合并这个问题&#xff0c;有的小伙伴想很简单&#xff0c;只需要将文件直接复制再其中的一个后面不就完事了吗。其实不然&#xff0c;因为我们如果要是需要将很多文件进行合并的话&#xff0c;就会产生很多问题的。总之&#xff0c;在现在…...

杀死僵尸进程ZooKeeperMain

关闭Hadoop后jps发现还有个进程ZooKeeperMain没有关闭&#xff0c;使用kill -9 <>也没有用&#xff0c;这种就是僵尸进程&#xff0c;需要用父进程ID来杀死 解决方法 话不多说&#xff0c;直接上解决方案&#xff0c; 1. 第一步 清楚需要关闭的进程ID&#xff0c;我…...

JavaScript class和function的区别

待整理&#xff1a; 一 二 Class 组件和 Function 组件是 React 中创建组件的两种主要方式。他们在语法和功能上有一些不同。以下分点是 Class 组件和 Function 组件在不同方面的对比&#xff1a; 1. 语法结构 Class 组件&#xff1a; import React, { Component } from …...

MySQL8.0修改mysql允许远程连接

1、连接服务器: mysql -u root -p2、看当前所有数据库&#xff1a;show databases; 3、进入mysql数据库&#xff1a;use mysql; 4、查看mysql数据库中所有的表&#xff1a;show tables; 5、查看user表中的数据&#xff1a;select Host, User,Password from user; 6、修改us…...

【算法训练-排序算法 二】【手撕排序】快速排序、堆排序、归并排序

废话不多说&#xff0c;喊一句号子鼓励自己&#xff1a;程序员永不失业&#xff0c;程序员走向架构&#xff01;本篇Blog的主题是【手撕排序系列】&#xff0c;使用【数组】这个基本的数据结构来实现&#xff0c;这个高频题的站点是&#xff1a;CodeTop&#xff0c;筛选条件为&…...

C# RestoreFormer 图像修复

效果 项目 代码 using Microsoft.ML.OnnxRuntime; using Microsoft.ML.OnnxRuntime.Tensors; using OpenCvSharp; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Imaging; using System.Windows.Forms;namespace 图像修复 {pu…...

yolov5+车辆重识别【附代码】

本篇文章主要是实现的yolov5和reid结合的车辆重识别项目。是在我之前实现的yolov5_reid行人重识别的代码上修改实现的baseline模型。 目录 相关参考资料 数据集说明 环境说明 项目使用说明 vehicle reid训练 yolov5车辆重识别 从视频中获取想要检测的车(待检测车辆) 车…...

C语言练习百题之#ifdef和#ifndef的应用

#if, #ifdef, 和 #ifndef 是C语言预处理指令&#xff0c;它们可以用于条件编译&#xff0c;帮助控制程序的编译过程。以下是各种应用场景以及一些注意事项&#xff1a; 1. 使用 #ifdef 和 #ifndef 检查宏是否定义&#xff1a; 应用场景: 检查宏是否已经在代码中定义&#xf…...

与C语言不同的基础语法

一、不同 1.可同时定义并初始化多个变量 2.有string字符串类型 3.可在循环中定义变量 #include<iostream> using namespace std; int main() {int a1,b2;//可同时定义并初始化多个变量string name;//字符串类型 char array[3]; for(int i1;i<3;i)//for中定义i变量…...

Python文件读写实战:处理日常任务的终极工具!

更多资料获取 &#x1f4da; 个人网站&#xff1a;涛哥聊Python Python文件的读写操作时&#xff0c;有很多需要考虑的细节&#xff0c;这包括文件打开方式、读取和写入数据的方法、异常处理等。 在本文中&#xff0c;将深入探讨Python中的文件操作&#xff0c;旨在提供全面的…...

思维模型 秩序

本系列文章 主要是 分享 思维模型&#xff0c;涉及各个领域&#xff0c;重在提升认知。秩序是事物正常运行的基石。有序的安排是成功的先决条件。 1 秩序的应用 1.1 秩序在不同科学领域中的应用 物理学和天文学&#xff1a; 物理学家通过研究原子和分子的有序排列来理解物质的…...

pyqt5移动鼠标时显示鼠标坐标

问题&#xff1a; 只有按住鼠标左键或者右键移动的时候才会获取坐标值&#xff0c;即使对QLabel控件使用setMouseTracking(True)也无法解决。 解决方法&#xff1a; 在初始化构造函数中加入 self.setMouseTracking(True) self.centralwidget.setMouseTracking(True) 并且对…...

分享一下开发回收废品小程序的步骤

随着人们环保意识的不断提高&#xff0c;回收利用已成为日常生活中不可或缺的一部分。回收小程序作为一种便捷、高效的回收方式&#xff0c;越来越受到人们的关注和喜爱。本文将探讨回收小程序的意义和作用&#xff0c;设计理念、功能特点、使用流程以及推广策略&#xff0c;并…...

568A和568B两种线序

现状 现在大家都是采用568B的线序 线序 标准568A&#xff1a;橙白-1&#xff0c;橙-2&#xff0c;绿白-3&#xff0c;蓝-4&#xff0c;蓝白-5&#xff0c;绿-6&#xff0c;棕白-7&#xff0c;棕-8 标准568B&#xff1a;绿白-1&#xff0c;绿-2&#xff0c;橙白-3&#x…...

kafka广播消费组停机后未删除优化

背景 kafka广播消息的时候为了保证groupId不重复&#xff0c;再创建的时间采用前缀时间戳的形式&#xff0c;这样可以保证每次启动的时候是创建的新的&#xff0c;但是 会出现一个问题&#xff1a;就是每次停机或者重启都会新建一个应用实例&#xff0c;关闭应用后并不会删除…...

Ubuntu系统下交叉编译openssl

一、参考资料 OpenSSL&&libcurl库的交叉编译 - hesetone - 博客园 二、准备工作 1. 编译环境 宿主机&#xff1a;Ubuntu 20.04.6 LTSHost&#xff1a;ARM32位交叉编译器&#xff1a;arm-linux-gnueabihf-gcc-11.1.0 2. 设置交叉编译工具链 在交叉编译之前&#x…...

iOS 26 携众系统重磅更新,但“苹果智能”仍与国行无缘

美国西海岸的夏天&#xff0c;再次被苹果点燃。一年一度的全球开发者大会 WWDC25 如期而至&#xff0c;这不仅是开发者的盛宴&#xff0c;更是全球数亿苹果用户翘首以盼的科技春晚。今年&#xff0c;苹果依旧为我们带来了全家桶式的系统更新&#xff0c;包括 iOS 26、iPadOS 26…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

【项目实战】通过多模态+LangGraph实现PPT生成助手

PPT自动生成系统 基于LangGraph的PPT自动生成系统&#xff0c;可以将Markdown文档自动转换为PPT演示文稿。 功能特点 Markdown解析&#xff1a;自动解析Markdown文档结构PPT模板分析&#xff1a;分析PPT模板的布局和风格智能布局决策&#xff1a;匹配内容与合适的PPT布局自动…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

vue3+vite项目中使用.env文件环境变量方法

vue3vite项目中使用.env文件环境变量方法 .env文件作用命名规则常用的配置项示例使用方法注意事项在vite.config.js文件中读取环境变量方法 .env文件作用 .env 文件用于定义环境变量&#xff0c;这些变量可以在项目中通过 import.meta.env 进行访问。Vite 会自动加载这些环境变…...

Map相关知识

数据结构 二叉树 二叉树&#xff0c;顾名思义&#xff0c;每个节点最多有两个“叉”&#xff0c;也就是两个子节点&#xff0c;分别是左子 节点和右子节点。不过&#xff0c;二叉树并不要求每个节点都有两个子节点&#xff0c;有的节点只 有左子节点&#xff0c;有的节点只有…...

RNN避坑指南:从数学推导到LSTM/GRU工业级部署实战流程

本文较长&#xff0c;建议点赞收藏&#xff0c;以免遗失。更多AI大模型应用开发学习视频及资料&#xff0c;尽在聚客AI学院。 本文全面剖析RNN核心原理&#xff0c;深入讲解梯度消失/爆炸问题&#xff0c;并通过LSTM/GRU结构实现解决方案&#xff0c;提供时间序列预测和文本生成…...

Xen Server服务器释放磁盘空间

disk.sh #!/bin/bashcd /run/sr-mount/e54f0646-ae11-0457-b64f-eba4673b824c # 全部虚拟机物理磁盘文件存储 a$(ls -l | awk {print $NF} | cut -d. -f1) # 使用中的虚拟机物理磁盘文件 b$(xe vm-disk-list --multiple | grep uuid | awk {print $NF})printf "%s\n"…...

return this;返回的是谁

一个审批系统的示例来演示责任链模式的实现。假设公司需要处理不同金额的采购申请&#xff0c;不同级别的经理有不同的审批权限&#xff1a; // 抽象处理者&#xff1a;审批者 abstract class Approver {protected Approver successor; // 下一个处理者// 设置下一个处理者pub…...