Spring Cloud Consul外部配置动态刷新源码解析

本文深入解析了Spring Cloud Consul如何使用Consul作为配置中心,通过ConfigWatch实现配置的定时监控,当配置更新时,通过RefreshEventListener监听并触发刷新。分析了ContextRefresher、PropertySourceBootstrapConfiguration和ConsulPropertySourceLocator的角色,展示了配置从Consul到应用的动态更新过程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Consul

Consul是一款中间件,可提供KV存储功能,同时提供了创建、修改、查询KV存储的HTTP API,因此可作为配置中心。

Spring Cloud Consul

Spring Cloud Consul是基于Spring Cloud的公共接口,提供了集成Consul配置能力的微服务框架。

源码分析

ConfigWatch

这个类中提供了一个定时任务

    @Override
	public void start() {
   
		if (this.running.compareAndSet(false, true)) {
   
			this.watchFuture = this.taskScheduler.scheduleWithFixedDelay(
					this::watchConfigKeyValues, this.properties.getWatch().getDelay());
		}
	}

该方法定时执行(getDelay():每当上一次执行完成后,经过固定延迟时间开始下一次执行)watchConfigKeyValues方法。

    @Timed("consul.watch-config-keys")
	public void watchConfigKeyValues() {
   
		if (this.running.get()) {
   
			for (String context : this.consulIndexes.keySet()) {
   

				// turn the context into a Consul folder path (unless our config format
				// are FILES)
				if (this.properties.getFormat() != FILES && !context.endsWith("/")) {
   
					context = context + "/";
				}

				try {
   
					Long currentIndex = this.consulIndexes.get(context);
					if (currentIndex == null) {
   
						currentIndex = -1L;
					}

					log.trace("watching consul for context '" + context + "' with index "
							+ currentIndex);

					// use the consul ACL token if found
					String aclToken = this.properties.getAclToken();
					if (StringUtils.isEmpty(aclToken)) {
   
						aclToken = null;
					}
					// 调用consul的HTTP API,获取配置
					Response<List<GetValue>> response = this.consul.getKVValues(context,
							aclToken,
							new QueryParams(this.properties.getWatch().getWaitTime(),
									currentIndex));

					// if response.value == null, response was a 404, otherwise it was a
					// 200
					// reducing churn if there wasn't anything
					if (response.getValue() != null && !response.getValue().isEmpty()) {
   
						Long newIndex = response.getConsulIndex();
						// currentIndex是缓存了KV配置的上一次更新的版本号,newIndex是当前版本号,若两者不等,则说明配置已更新,所以需要刷新
						if (newIndex != null && !newIndex.equals(currentIndex)) {
   
							// don't publish the same index again, don't publish the first
							// time (-1) so index can be primed
							if (!this.consulIndexes.containsValue(newIndex)
									&& !currentIndex.equals(-1L)) {
   
								log.trace("Context " + context + " has new index "
										+ newIndex);
								RefreshEventData data = new RefreshEventData(context,
										currentIndex, newIndex);
								// 通过Spring的事件机制触发配置动态刷新
								this.publisher.publishEvent(
										new RefreshEvent(this, data, data.toString()));
							}
							else if (log.isTraceEnabled()) {
   
								log.trace("Event for index already published for context "
										+ context);
							}
							this.consulIndexes.put(context, newIndex);
						}
						else if (log.isTraceEnabled()) {
   
							log.trace("Same index for context " + context);
						}
					}
					else if (log.isTraceEnabled()) {
   
						log.trace("No value for context " + context);
					}

				}
				catch (Exception e) {
   
					// only fail fast on the initial query, otherwise just log the error
					if (this.firstTime && this.properties.isFailFast()) {
   
						log.error(
								"Fail fast is set and there was an error reading configuration from consul.");
						ReflectionUtils.rethrowRuntimeException(e);
					}
					else if (log.isTraceEnabled()) {
   
						log.trace("Error querying consul Key/Values for context '"
								+ context + "'", e);
					}
					else if 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值