Spring Cloud Consul Config 配置刷新

2019-06-13  本文已影响0人  天草二十六_简村人

1、不同于 Spring cloud config 的配置更新机制(配置更新之后使用 bus 将配置变动推送给各个服务),Spring Cloud Consul Config是通过HTTP的方式跟Consul交互的,更新是实时的吗?
org.springframework.cloud.consul.config.ConfigWathc中定时方法watchConfigKeyValues(),默认每个1秒执行一次(可通过spring.cloud.consul.config.watch.delay自定义时间),去Consul获取最新的信息,配置发生变化时,Spring通过ApplicationEventPublisher重新刷新配置。Consul Config通过这种方式实现实时生效的效果。

2、客户端如何发现配置变更了?
Consul返回的数据中每一项配置都会有"consulIndex"属性,如果更新,属性就会自增。
Spring Cloud Consul Config 就是通过缓存“consulIndex”判断配置是否发生改变。

//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by Fernflower decompiler)
//

package org.springframework.cloud.consul.config;

import com.ecwid.consul.v1.ConsulClient;
import com.ecwid.consul.v1.QueryParams;
import com.ecwid.consul.v1.Response;
import com.ecwid.consul.v1.kv.model.GetValue;
import io.micrometer.core.annotation.Timed;
import java.beans.ConstructorProperties;
import java.io.Closeable;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.concurrent.atomic.AtomicBoolean;
import javax.annotation.PostConstruct;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.cloud.consul.config.ConsulConfigProperties.Format;
import org.springframework.cloud.endpoint.event.RefreshEvent;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.ReflectionUtils;
import org.springframework.util.StringUtils;

public class ConfigWatch implements Closeable, ApplicationEventPublisherAware {
    private static final Log log = LogFactory.getLog(ConfigWatch.class);
    private final ConsulConfigProperties properties;
    private final ConsulClient consul;
    private LinkedHashMap<String, Long> consulIndexes;
    private final AtomicBoolean running;
    private ApplicationEventPublisher publisher;
    private boolean firstTime;

    /** @deprecated */
    @Deprecated
    public ConfigWatch(ConsulConfigProperties properties, List<String> contexts, ConsulClient consul) {
        this(properties, consul, new LinkedHashMap());
    }

    public ConfigWatch(ConsulConfigProperties properties, ConsulClient consul, LinkedHashMap<String, Long> initialIndexes) {
        this.running = new AtomicBoolean(false);
        this.firstTime = true;
        this.properties = properties;
        this.consul = consul;
        this.consulIndexes = new LinkedHashMap(initialIndexes);
    }

    public void setApplicationEventPublisher(ApplicationEventPublisher publisher) {
        this.publisher = publisher;
    }

    @PostConstruct
    public void start() {
        this.running.compareAndSet(false, true);
    }

    @Scheduled(
        fixedDelayString = "${spring.cloud.consul.config.watch.delay:1000}"
    )
    @Timed("consul.watch-config-keys")
    public void watchConfigKeyValues() {
        if (this.running.get()) {
            Iterator var1 = this.consulIndexes.keySet().iterator();

            while(var1.hasNext()) {
                String context = (String)var1.next();
                if (this.properties.getFormat() != Format.FILES && !context.endsWith("/")) {
                    context = context + "/";
                }

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

                    String aclToken = this.properties.getAclToken();
                    if (StringUtils.isEmpty(aclToken)) {
                        aclToken = null;
                    }

                    Response<List<GetValue>> response = this.consul.getKVValues(context, aclToken, new QueryParams((long)this.properties.getWatch().getWaitTime(), currentIndex.longValue()));
                    if (response.getValue() != null && !((List)response.getValue()).isEmpty()) {
                        Long newIndex = response.getConsulIndex();
                        if (newIndex != null && !newIndex.equals(currentIndex)) {
                            if (!this.consulIndexes.containsValue(newIndex) && !currentIndex.equals(-1L)) {
                                ConfigWatch.RefreshEventData data = new ConfigWatch.RefreshEventData(context, currentIndex, newIndex);
                                this.publisher.publishEvent(new RefreshEvent(this, data, data.toString()));
                            }

                            this.consulIndexes.put(context, newIndex);
                        }
                    }
                } catch (Exception var8) {
                    if (this.firstTime && this.properties.isFailFast()) {
                        log.error("Fail fast is set and there was an error reading configuration from consul.");
                        ReflectionUtils.rethrowRuntimeException(var8);
                    } else if (log.isTraceEnabled()) {
                        log.trace("Error querying consul Key/Values for context '" + context + "'", var8);
                    } else if (log.isWarnEnabled()) {
                        log.warn("Error querying consul Key/Values for context '" + context + "'. Message: " + var8.getMessage());
                    }
                }
            }
        }

        this.firstTime = false;
    }

    public void close() {
        this.running.compareAndSet(true, false);
    }

    static class RefreshEventData {
        private final String context;
        private final Long prevIndex;
        private final Long newIndex;

        @ConstructorProperties({"context", "prevIndex", "newIndex"})
        public RefreshEventData(String context, Long prevIndex, Long newIndex) {
            this.context = context;
            this.prevIndex = prevIndex;
            this.newIndex = newIndex;
        }

        public String getContext() {
            return this.context;
        }

        public Long getPrevIndex() {
            return this.prevIndex;
        }

        public Long getNewIndex() {
            return this.newIndex;
        }

        public boolean equals(Object o) {
            if (o == this) {
                return true;
            } else if (!(o instanceof ConfigWatch.RefreshEventData)) {
                return false;
            } else {
                ConfigWatch.RefreshEventData other = (ConfigWatch.RefreshEventData)o;
                if (!other.canEqual(this)) {
                    return false;
                } else {
                    label47: {
                        Object this$context = this.getContext();
                        Object other$context = other.getContext();
                        if (this$context == null) {
                            if (other$context == null) {
                                break label47;
                            }
                        } else if (this$context.equals(other$context)) {
                            break label47;
                        }

                        return false;
                    }

                    Object this$prevIndex = this.getPrevIndex();
                    Object other$prevIndex = other.getPrevIndex();
                    if (this$prevIndex == null) {
                        if (other$prevIndex != null) {
                            return false;
                        }
                    } else if (!this$prevIndex.equals(other$prevIndex)) {
                        return false;
                    }

                    Object this$newIndex = this.getNewIndex();
                    Object other$newIndex = other.getNewIndex();
                    if (this$newIndex == null) {
                        if (other$newIndex != null) {
                            return false;
                        }
                    } else if (!this$newIndex.equals(other$newIndex)) {
                        return false;
                    }

                    return true;
                }
            }
        }

        protected boolean canEqual(Object other) {
            return other instanceof ConfigWatch.RefreshEventData;
        }

        public int hashCode() {
            int PRIME = true;
            int result = 1;
            Object $context = this.getContext();
            int result = result * 59 + ($context == null ? 43 : $context.hashCode());
            Object $prevIndex = this.getPrevIndex();
            result = result * 59 + ($prevIndex == null ? 43 : $prevIndex.hashCode());
            Object $newIndex = this.getNewIndex();
            result = result * 59 + ($newIndex == null ? 43 : $newIndex.hashCode());
            return result;
        }

        public String toString() {
            return "ConfigWatch.RefreshEventData(context=" + this.getContext() + ", prevIndex=" + this.getPrevIndex() + ", newIndex=" + this.getNewIndex() + ")";
        }
    }
}
上一篇 下一篇

猜你喜欢

热点阅读