祥安阁风水网是哪个公司做的网站/白杨seo博客
Nacos配置文件读取
本篇文章是探究,springboot启动时nacos是如何将配置中心的配置读取到springboot环境中的
PropertySourceLocator
org.springframework.cloud.bootstrap.config.PropertySourceLocator 是 springcloud 定义的一个顶级接口,用来定义所有实现类加载自定义配置的类,数据的调用则是在 PropertySourceBootstrapConfiguration 自动装配中
public interface PropertySourceLocator {/*** 创建配置源** @param environment 环境* @return {@code PropertySource<?> }* @date 2023-08-09 11:43:03*/PropertySource<?> locate(Environment environment);default Collection<PropertySource<?>> locateCollection(Environment environment) {return locateCollection(this, environment);}static Collection<PropertySource<?>> locateCollection(PropertySourceLocator locator,Environment environment) {//调用 locate() 方法构建配置对象PropertySource<?> propertySource = locator.locate(environment);//如果为空直接返回空的集合if (propertySource == null) {return Collections.emptyList();}//判断当前对象是否是 CompositePropertySource 多配置文件对象聚合类,这是nacos的默认实现类,会构建多个配置对象if (CompositePropertySource.class.isInstance(propertySource)) {Collection<PropertySource<?>> sources = ((CompositePropertySource) propertySource).getPropertySources();List<PropertySource<?>> filteredSources = new ArrayList<>();//将数据获取出来for (PropertySource<?> p : sources) {if (p != null) {filteredSources.add(p);}}return filteredSources;}else {return Arrays.asList(propertySource);}}}
PropertySourceBootstrapConfiguration
配置属性的全局自动配置类,由 springcloud 定义并且在 springboot初始化时进行调用;配置类中的属性就注入了所有的 PropertySourceLocator接口的实现类
public class PropertySourceBootstrapConfiguration implementsApplicationContextInitializer<ConfigurableApplicationContext>, Ordered {
/*** 自定注入所有的实现类 PropertySourceLocator*/@Autowired(required = false)private List<PropertySourceLocator> propertySourceLocators = new ArrayList<>();}
initialize 方法在springboot调用 ApplicationContextInitializer 是进行执行
public void initialize(ConfigurableApplicationContext applicationContext) {//将nacos中的配置构建为 PropertySource 配置属性对象List<PropertySource<?>> composite = new ArrayList<>();//根据@Order注解进行排序AnnotationAwareOrderComparator.sort(this.propertySourceLocators);boolean empty = true;//获取到环境对象ConfigurableEnvironment environment = applicationContext.getEnvironment();//循环遍历for (PropertySourceLocator locator : this.propertySourceLocators) {//调用实现方法进行构建配置对象 PropertySourceCollection<PropertySource<?>> source = locator.locateCollection(environment);//如果配置出来的 PropertySource 为空,那么直接跳过到下一个if (source == null || source.size() == 0) {continue;}List<PropertySource<?>> sourceList = new ArrayList<>();//根据配置出来的 PropertySource 在进行包装,除了 EnumerablePropertySource枚举类型配置源,其他的都是 SimpleBootstrapPropertySourcefor (PropertySource<?> p : source) {if (p instanceof EnumerablePropertySource) {EnumerablePropertySource<?> enumerable = (EnumerablePropertySource<?>) p;sourceList.add(new BootstrapPropertySource<>(enumerable));}else {sourceList.add(new SimpleBootstrapPropertySource(p));}}logger.info("Located property source: " + sourceList);composite.addAll(sourceList);empty = false;}//如果配置不为空的话if (!empty) {//获取到环境中的属性配置类,MutablePropertySources 这个类中包含了一个 List<PropertySource<?>>MutablePropertySources propertySources = environment.getPropertySources();//解析日志配置的占位符String logConfig = environment.resolvePlaceholders("${logging.config:}");//解析日志文件出来LogFile logFile = LogFile.get(environment);//移除掉 bootstrapProperties 这个配置源,因为这个配置源一般在容器启动之前就已经全局加载了,不需要再使用for (PropertySource<?> p : environment.getPropertySources()) {if (p.getName().startsWith(BOOTSTRAP_PROPERTY_SOURCE_NAME)) {propertySources.remove(p.getName());}}//将构建出来的配置源添加到环境中去insertPropertySources(propertySources, composite);//再次构建日志系统相关的配置reinitializeLoggingSystem(environment, logConfig, logFile);//设置日志级别setLogLevels(applicationContext, environment);//这里处理需要包含的环境配置,将配置文件中存在 spring.profiles.include 设置到环境中handleIncludedProfiles(environment);}}
NacosPropertySourceLocator
nacos实现的配置定位器,包含的属性值
- nacosPropertySourceBuilder:nacos的配置属性构建器,就是它去拉取配置然后构建 PropertySource
- nacosConfigProperties:nacos的配置属性类
- nacosConfigManager:nacos配置管理器
public class NacosPropertySourceLocator implements PropertySourceLocator {private static final String NACOS_PROPERTY_SOURCE_NAME = "NACOS";//分隔符private static final String DOT = ".";private static final String SEP1 = "-";//配置的构建器private NacosPropertySourceBuilder nacosPropertySourceBuilder;//nacos配置private NacosConfigProperties nacosConfigProperties;//nacos配置管理器private NacosConfigManager nacosConfigManager;
}
实现方法中,创建了一个配置构建器对象 **nacosPropertySourceBuilder **传入 ConfigService 属性,ConfigService,发起请求的就是 ConfigService类
public PropertySource<?> locate(Environment env) {nacosConfigProperties.setEnvironment(env);//配置服务(NacosConfigService),比较核心通过http长轮询的方式获取配置,2.0之后改为grpcConfigService configService = nacosConfigManager.getConfigService();if (null == configService) {log.warn("no instance of config service found, can't load config from nacos");return null;}long timeout = nacosConfigProperties.getTimeout();//创建一个配置的构建器nacosPropertySourceBuilder = new NacosPropertySourceBuilder(configService,timeout);//先获取到配置文件中指定的名称String name = nacosConfigProperties.getName();//获取到配置的前缀String dataIdPrefix = nacosConfigProperties.getPrefix();if (StringUtils.isEmpty(dataIdPrefix)) {dataIdPrefix = name;}//如果配置都为空,那么直接获取 spring.application.name 配置的名称if (StringUtils.isEmpty(dataIdPrefix)) {dataIdPrefix = env.getProperty("spring.application.name");}//创建一个配置名称为 nacos 的聚合配置属性对象CompositePropertySource composite = new CompositePropertySource(NACOS_PROPERTY_SOURCE_NAME);//加载共享配置文件,分组为默认loadSharedConfiguration(composite);//加载扩展配置文件loadExtConfiguration(composite);//加载配置文件loadApplicationConfiguration(composite, dataIdPrefix, nacosConfigProperties, env);return composite;}/*** 根据文件名称和分组加载配置文件,拼接激活的环境后缀** @param compositePropertySource 复合属性来源* @param dataIdPrefix 数据id前缀* @param properties 配置属性* @param environment 环境* @date 2023-08-09 13:43:32*/
private void loadApplicationConfiguration(CompositePropertySource compositePropertySource, String dataIdPrefix,NacosConfigProperties properties, Environment environment) {//获取到指定的文件后缀,默认是propertiesString fileExtension = properties.getFileExtension();//获取到配置的分组String nacosGroup = properties.getGroup();// 加载没有带后缀的配置文件例如:product 因为这里直接将服务名称作为了dataIdloadNacosDataIfPresent(compositePropertySource, dataIdPrefix, nacosGroup,fileExtension, true);// 加载带后缀的配置文件例如:product.propertiesloadNacosDataIfPresent(compositePropertySource,dataIdPrefix + DOT + fileExtension, nacosGroup, fileExtension, true);// 根据激活的环境去拼接对应的配置文件名称并且进行加载for (String profile : environment.getActiveProfiles()) {String dataId = dataIdPrefix + SEP1 + profile + DOT + fileExtension;/*** 1. 先通过 NacosPropertySourceRepository 判断配置文件是否已经加载了* 2. 在 nacosPropertySourceBuilder 通过 configService 加载配置文件,加载完成了后会将其注册到 NacosPropertySourceRepository* 3. 在上下文创建完成后根据配置文件再注册对应的监听器 NacosContextRefresher*/loadNacosDataIfPresent(compositePropertySource, dataId, nacosGroup,fileExtension, true);}}/*** 通过 ConfigService 服务去拉取配置文件,然后在构建为 NacosPropertySource** @param dataId 数据标识* @param group 组名* @param fileExtension 文件扩展名* @param isRefreshable 是否可刷新* @return {@code NacosPropertySource }* @date 2023-08-09 13:42:22*/private NacosPropertySource loadNacosPropertySource(final String dataId,final String group, String fileExtension, boolean isRefreshable) {if (NacosContextRefresher.getRefreshCount() != 0) {if (!isRefreshable) {return NacosPropertySourceRepository.getNacosPropertySource(dataId,group);}}return nacosPropertySourceBuilder.build(dataId, group, fileExtension,isRefreshable);}
NacosConfigService
nacos的配置服务,用于发送请求跟nacos注册中心进行交互的组件
public class NacosConfigService implements ConfigService {private static final Logger LOGGER = LogUtils.logger(NacosConfigService.class);/*** 2.0版本之后将会删除,2.0之前采用的是http长轮询的方式,2.0之后就采用rpc*/@DeprecatedServerHttpAgent agent = null;/*** 客户端工作器,客户端将配置的监听器注册到这里,然后由这里通过线程池进行长轮询监听配置文件的改变*/private final ClientWorker worker;//命名空间private String namespace;//配置文件的过滤器链管理器private final ConfigFilterChainManager configFilterChainManager;}
- serverListManager :先构建服务器列表的管理器
- worker:真正执行配置监听和创建的服务
public NacosConfigService(Properties properties) throws NacosException {//验证参数ValidatorUtils.checkInitParam(properties);//初始化命名空间的名称initNamespace(properties);//通过 ServiceLoader 加载出来的 ConfigFilter 实现类,然后将其添加到 ConfigFilterChainManager 中this.configFilterChainManager = new ConfigFilterChainManager(properties);/*** 启动服务端列表管理器,如果nacos是集群配置,其中会将配置的对应的服务器集群的地址进行解析*/ServerListManager serverListManager = new ServerListManager(properties);//定时每30秒拉取一次服务的列表serverListManager.start();/*** 启动本地配置信息处理器,2.0之前采用的http长轮询的方式进行监听,2.0之后采用rpc的方式进行监听* 通过一个阻塞队列进行线程的阻塞,默认是5秒钟便会唤醒一次,然后进行一次配置变动的监听更新,如果* 有监听器进行注册,那么会立即执行一次*/this.worker = new ClientWorker(this.configFilterChainManager, serverListManager, properties);// will be deleted in 2.0 later versionsagent = new ServerHttpAgent(serverListManager);}
根据对应的配置名称和组名拉取对应的配置信息
/*** 根据对应的命名空间、dataId、group、超时时间获取配置文件** @param dataId dataId* @param group group* @param timeoutMs read timeout* @return* @throws NacosException*/@Overridepublic String getConfig(String dataId, String group, long timeoutMs) throws NacosException {return getConfigInner(namespace, dataId, group, timeoutMs);}
添加配置文件变动的监听器
/*** 添加监听器** @param dataId 数据标识* @param group 组* @param listener 侦听器* @author zhonghaijun* @date 2023-08-09 13:45:52*/@Overridepublic void addListener(String dataId, String group, Listener listener) throws NacosException {worker.addTenantListeners(dataId, group, Arrays.asList(listener));}
手动推送配置
/*** 发布配置** @param dataId 数据标识* @param group 组* @param content 内容* @return boolean* @author zhonghaijun* @date 2023-08-09 14:44:10*/@Overridepublic boolean publishConfig(String dataId, String group, String content) throws NacosException {return publishConfig(dataId, group, content, ConfigType.getDefaultType().getType());}
ClientWorker
客户端工作器,这个组件专门用于推送配置、监听配置、获取配置等服务
- ConfigRpcTransportClient:用于发起rpc的客户端,start() 方法将会回调到 ClientWorker.startInternal() 方法中
public ClientWorker(final ConfigFilterChainManager configFilterChainManager, ServerListManager serverListManager,final Properties properties) throws NacosException {this.configFilterChainManager = configFilterChainManager;//初始化参数超时时间、配置重试时间、是否开启远程配置同步(开启后在配置配置文件监听时会先去远程服务器上对内容进行同步一次)init(properties);//创建rpc客户端agent = new ConfigRpcTransportClient(properties, serverListManager);//创建一个定时任务的线程池,提交一个守护线程ScheduledExecutorService executorService = Executors.newScheduledThreadPool(ThreadUtils.getSuitableThreadCount(1), r -> {Thread t = new Thread(r);t.setName("com.alibaba.nacos.client.Worker");t.setDaemon(true);return t;});agent.setExecutor(executorService);/*** 启动rpc客户端,* 调用 当期类的 startInternal() 方法,这个方法监听 listenExecutebell阻塞队列的任务* 在客户端添加配置监听服务时,会向 listenExecutebell阻塞队列中添加一个任务,这个任务会去远程服务器上获取配置内容*/agent.start();}
/*** 根据命名空间添加一个配置的监听器** @param dataId dataId of data* @param group group of data* @param listeners listeners* @throws NacosException nacos exception*/public void addTenantListeners(String dataId, String group, List<? extends Listener> listeners)throws NacosException {//如果分组为空,那么就直接以默认的分组进行处理group = blank2defaultGroup(group);//获取到对应的租户信息,就是namespace命名空间String tenant = agent.getTenant();//创建缓存数据,如果开启了 enableRemoteSyncConfig,会去远程服务拉取配置信息CacheData cache = addCacheDataIfAbsent(dataId, group, tenant);synchronized (cache) {//添加监听器for (Listener listener : listeners) {cache.addListener(listener);}cache.setSyncWithServer(false);//向队列listenExecutebell中添加一个元素,用于唤醒监听线程,在startInternal() 方法中进行监听agent.notifyListenConfig();}}
相关文章:

Nacos配置文件读取源码解析
Nacos配置文件读取 本篇文章是探究,springboot启动时nacos是如何将配置中心的配置读取到springboot环境中的 PropertySourceLocator org.springframework.cloud.bootstrap.config.PropertySourceLocator 是 springcloud 定义的一个顶级接口,用来定义所…...

Linux0.11内核源码解析-fcntl.c/iotcl.c/stat.c
fcntl fcntl.c实现了文件控制系统调用fcntl和两个文件句柄描述符的复制系统调用dup()和dup2()。 dup返回当前值最小的未用句柄,dup2返回指定新句柄的数值,句柄的复制操作主要用在文件的标准输入、输出重定向和管道方面。 dupfd 复制文件句柄ÿ…...

OpenStack简介
OpenStack简介 目录 OpenStack简介 1、云计算模式2、云计算 虚拟化 openstack之间的关系?3、OpenStack 中有哪些组件?4、计算节点负责虚拟机运行5、网络节点负责对外网络与内网之间的通信 5.1 网络节点仅包含Neutron服务5.2 网络节点包含三个网络端口6、…...

二分法的应用
文章目录 什么是二分法🎮二分查找的优先级二分查找的步骤💥图解演示🧩 代码演示🫕python程序实现🐈⬛C程序实现🐕🦺C程序实现🐯Java程序实现🐳 非常规类二分查找&…...

ChatGPT在大规模数据处理和信息管理中的应用如何?
ChatGPT作为一种强大的自然语言处理模型,在大规模数据处理和信息管理领域有着广泛的应用潜力。它可以利用其文本生成、文本理解和问答等能力,为数据分析、信息提取、知识管理等任务提供智能化的解决方案。以下将详细介绍ChatGPT在大规模数据处理和信息管…...

【算法篇C++实现】五大常规算法
文章目录 🚀一、分治法⛳(一)算法思想⛳(二)相关代码 🚀二、动态规划算法⛳(一)算法思想⛳(二)相关代码 🚀三、回溯算法⛳(一…...

MySQL和钉钉单据接口对接
MySQL和钉钉单据接口对接 数据源系统:钉钉 钉钉(DingTalk)是阿里巴巴集团打造的企业级智能移动办公平台,是数字经济时代的企业组织协同办公和应用开发平台。钉钉将IM即时沟通、钉钉文档、钉闪会、钉盘、Teambition、OA审批、智能人事、钉工牌…...

layui的基本使用-日期控件的业务场景使用入门实战案例一
效果镇楼; 1 前端UI层面; <!DOCTYPE html> <html lang"en"> <head><meta charset"UTF-8"><meta http-equiv"X-UA-Compatible" content"IEedge"><meta name"viewport&…...

【2.1】Java微服务:详解Hystrix
✅作者简介:大家好,我是 Meteors., 向往着更加简洁高效的代码写法与编程方式,持续分享Java技术内容。 🍎个人主页:Meteors.的博客 💞当前专栏: Java微服务 ✨特色专栏: 知识分享 &am…...

Apache2.4源码安装与配置
环境准备 openssl-devel pcre-devel expat-devel libtool gcc libxml2-devel 这些包要提前安装,否则httpd编译安装时候会报错 下载源码、解压缩、软连接 1、wget下载[rootnode01 ~]# wget https://downloads.apache.org/httpd/httpd-2.4.57.tar.gz --2023-07-20 …...

Flume原理剖析
一、介绍 Flume是一个高可用、高可靠,分布式的海量日志采集、聚合和传输的系统。Flume支持在日志系统中定制各类数据发送方,用于收集数据;同时,Flume提供对数据进行简单处理,并写到各种数据接受方(可定制&…...

【leetcode】202. 快乐数(easy)
编写一个算法来判断一个数 n 是不是快乐数。 「快乐数」 定义为: 对于一个正整数,每一次将该数替换为它每个位置上的数字的平方和。然后重复这个过程直到这个数变为 1,也可能是 无限循环 但始终变不到 1。如果这个过程 结果为 1,…...

如何用瀑布图分析公司年报
原创: MicroStrategy微策略中国 , Jiping Sun 微策略企业级数据分析与移动应用9月21日2018年 摘要:利用达析报告开箱即用的瀑布图来展示各个度量值如何增加或减少。下载MicroStrategy Desktop 10.11以上版本,自己动手创建瀑布图。 瀑布图是由…...

Asynq: 基于Redis实现的Go生态分布式任务队列和异步处理库
Asynq[1]是一个Go实现的分布式任务队列和异步处理库,基于redis,类似Ruby的sidekiq[2]和Python的celery[3]。Go生态类似的还有machinery[4]和goworker 同时提供一个WebUI asynqmon[5],可以源码形式安装或使用Docker image, 还可以和Prometheus…...

保证率计算公式 正态分布
在正态分布中,如果我们要计算一个给定区间内的保证率,可以使用下面的计算公式: 找到给定保证率对应的标准正态分布的z值。可以使用标准正态分布表或计算器进行查询。例如,对于95%的保证率,对应的z值为1.96。 使用z值和…...

docker容器监控:Cadvisor+InfluxDB+Grafana的安装部署
目录 CadvisorInfluxDBGrafan安装部署 1、安装docker-ce 2、阿里云镜像加速器 3、下载组件镜像 4、创建自定义网络 5、创建influxdb容器 6、创建Cadvisor 容器 7、查看Cadvisor 容器: (1)准备测试镜像 (2)通…...

论文讲解——TPU-MLIR: A Compiler For TPU Using MLIR
论文讲解——TPU-MLIR: A Compiler For TPU Using MLIR https://arxiv.org/pdf/2210.15016.pdf概览模型转换TranslationCanonicalizeLoweringLayerGroup BufferizationCalibration QuantizationCorrectness Check相关资料 https://arxiv.org/pdf/2210.15016.pdf 本文将对TPU…...

基于最新导则下生态环评报告编制技术暨报告篇、制图篇、指数篇、综合应用篇系统性实践技能提升
查看原文>>>基于最新导则下生态环评报告编制技术暨报告篇、制图篇、指数篇、综合应用篇系统性实践技能提升 目录 专题一、生态环评报告编制规范 专题二、土地利用图 专题三、植被类型及植被覆盖度图 专题四、物种适宜生境分布图 专题五、生物多样性测定 专题六…...

NGZORRO:动态表单/模型驱动 的相关问题
官网的demo的[nzFor]"control.controlInstance",似乎是靠[formControlName]"control.controlInstance"来关联的。 <form nz-form [formGroup]"validateForm" (ngSubmit)"submitForm()"><nz-form-item *ngFor&quo…...

第十七次CCF计算机软件能力认证
第一题:小明种苹果 n , m map(int , input().split()) t , k , p 0 , 0 , -1 for _ in range(n):l list(map(int , input().split()))t sum(l)x -sum(l[i] for i in range(1 , len(l)))if x > p:p xk _ 1 print(t , k , p) 第二题:小明种苹…...

ApplicationContext在Spring Boot中是如何创建的?
一、ApplicationContext在Spring Boot中是如何创建的? 1. SpringApplication ApplicationContextFactory有三个实现类,分别是AnnotationConfigReactiveWebServerApplicationContext.Factory、AnnotationConfigServletWebServerApplicationContext.Facto…...

后端开发7.轮播图模块【mongdb开发】
概述 轮播图模块数据库采用mongdb开发 效果图 数据库设计 创建数据库 use sc; 添加数据 db.banner.insertMany([ {bannerId:"1",bannerName:"商城轮播图1",bannerUrl:"http://xx:8020/img/轮播图/shop1.png"}, {bannerId:"2"…...

Linux常用命令(一):创建文件目录
一、touch: 1、作用: 1). 改变已有文件的时间戳属性,修改文件时间戳时,用户必须的文件的属主,或者拥有写文件的权限 2). 创建新的空文件 2、语法: touch [option] 文件名 ,后面可跟多个文件名3、示例 …...

如何创建一个Vue组件?如何在父组件和子组件之间传递数据?如何在子组件中向父组件发送消息?
1、如何创建一个Vue组件? 要创建一个Vue组件,可以按照以下步骤进行: 安装Vue CLI(如果还没有安装): npm install -g vue/cli创建一个新的Vue组件: vue create my-component在 src/component…...

设计模式之适配器模式
一、概述 将一个类的接口转换成客户希望的另外一个接口。Adapter模式使得原本由于接口不兼容而不能一起工作的那些类可以一起工作。 二、适用性 1.你想使用一个已经存在的类,而它的接口不符合你的需求。 2.你想创建一个可以复用的类,该类可以与其他不…...

让ChatGPT介绍一下ChatGPT(ChatGPT的自我介绍)
ChatGPT是这样介绍自己的: ChatGPT是由OpenAI开发的一种基于大规模预训练的语言模型。它是建立在GPT(Generative Pre-trained Transformer)架构的基础上,经过大量的数据训练而成。 ChatGPT旨在通过对话与用户进行交互࿰…...

CentOS 7 构建 LVS-DR 群集
一、LVS-DR集群摘要 LVS(Linux Virtual Server)是一个用于构建可扩展和高可用性的负载均衡集群的软件。它基于Linux操作系统,并提供了一种将网络流量分发到多个后端服务器的机制。 二、基本工作原理 配置负载均衡器:在LVS集群中…...

MySQL8.0.33二进制包安装与部署
官方文档 https://downloads.mysql.com/archives/community/https://dev.mysql.com/doc/refman/8.1/en/binary-installation.html官方文档操作步骤 # Preconfiguration setup $> groupadd mysql $> useradd -r -g mysql -s /bin/false mysql # Beginning of source-build…...

RocketMQ发送消息失败:error CODE: 14 DESC: service not available now, maybe disk full
在执行业务时,发现MQ控制台没有查询到消息,在日志中发现消息发送失败,报错error CODE: 14 DESC: service not available now, maybe disk full 分析报错应该是磁盘空间不足,导致broker不能进行正常的消息存储刷盘,去查…...

1.Fay-UE5数字人工程导入(UE数字人系统教程)
非常全面的数字人解决方案(含源码) Fay-UE5数字人工程导入 1、工程下载:xszyou/fay-ue5: 可对接fay数字人的ue5工程 (github.com) 2、ue5下载安装:Unreal Engine 5 3、ue5插件安装 依次安装以下几个插件 4、双击运行工程 5、切换中文 6、检…...