All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ijson.config.impl.RemoteConfigWithCache Maven / Gradle / Ivy

package com.ijson.config.impl;

import com.google.common.base.MoreObjects;
import com.google.common.io.Files;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import com.google.common.util.concurrent.Uninterruptibles;
import com.ijson.config.helper.FileUpdateWatcher;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.util.List;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.TimeUnit;

import static com.ijson.config.base.ConfigConstants.CACHE_FILE_SIZE;

/**
 * @author *
 */
public class RemoteConfigWithCache extends RemoteConfig {


    public static final Logger log = LoggerFactory.getLogger(RemoteConfigWithCache.class);

    private static final ThreadFactory FACTORY =
            new ThreadFactoryBuilder().setDaemon(true).setNameFormat("config-load-%d").build();
    private final File cacheFile;
    /**
     * 延迟加载远程配置初始值,避免加载配置影响启动
     */
    private boolean loadedFromZookeeper = false;

    public RemoteConfigWithCache(String name, String basePath, List paths, File cacheFile) {
        super(name, basePath, paths);
        this.cacheFile = cacheFile;
    }

    public File getCacheFile() {
        return cacheFile;
    }

    @Override
    public void loadAndWatchChanges() {
        //有本地配置就先从本地加载
        if (cacheFile.exists() && cacheFile.length() > CACHE_FILE_SIZE) {
            try {
                copyOf(Files.toByteArray(cacheFile));
                FACTORY.newThread(() -> {
                    //延迟加载zookeeper上的配置,避免服务启动过慢
                    Uninterruptibles.sleepUninterruptibly(15, TimeUnit.SECONDS);
                    initZookeeper();
                }).start();
            } catch (IOException e) {
                log.error("cannot read {}", cacheFile);
                initZookeeper();
            }
        } else {
            //本地没有则直接从zookeeper加载
            initZookeeper();
        }
        //注册本地配置变更通知回调
        FileUpdateWatcher.getInstance().watch(cacheFile.toPath(), (path, content) -> {
            log.info("local change: {}", path);
            refresh(content);
        });
    }

    private void refresh(byte[] content) {
        if (isChanged(content) && content != null && content.length > 0) {
            copyOf(content);
            try {
                //已经加载过,就不要再通过本地文件修改通知再加载1次了
                FileUpdateWatcher.getInstance().mask(cacheFile.toPath());
                Files.write(content, cacheFile);
            } catch (IOException e) {
                log.error("cannot write {}", cacheFile);
            }
            notifyListeners();
        }
    }

    @Override
    protected void reload(byte[] content) {
        //避免首次启动,远程配置不存在反而覆盖了本地配置
        boolean contentEmpty = content == null || content.length == 0;
        if (contentEmpty && !loadedFromZookeeper) {
            log.warn("{} deleted, wont clean local for safety", getPath());
            return;
        }
        loadedFromZookeeper = true;
        refresh(content);
    }

    @Override
    public String toString() {
        return MoreObjects.toStringHelper(this)
                .add("name", getName())
                .add("cacheFile", cacheFile)
                .add("zkPath", getPath())
                .toString();
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy