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

com.github.autoconf.impl.RemoteConfigWithCache Maven / Gradle / Ivy

The newest version!
package com.github.autoconf.impl;

import com.github.autoconf.api.IFileListener;
import com.github.autoconf.watcher.FileUpdateWatcher;
import com.google.common.base.MoreObjects;
import com.google.common.collect.Sets;
import com.google.common.io.Files;
import org.apache.curator.framework.CuratorFramework;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.IOException;
import java.nio.file.Path;
import java.util.List;
import java.util.Set;

/**
 * 基于远程zookeeper文件的配置,启用本地文件缓存.
 * 
 * 1.启动首先查找本地配置,如果有的话,会先使用本地配置.
 * 2.同时启动异步线程检查远程zookeeper的配置.
 * 3.远程zookeeper改动内容会同步些往本地文件缓存.
 * 
* Created by lirui on 2015/9/30. */ public class RemoteConfigWithCache extends RemoteConfig { private static final Logger LOG = LoggerFactory.getLogger(RemoteConfigWithCache.class); private final File cacheFile; /** * 延迟加载远程配置初始值,避免加载配置影响启动 */ private long delaySeconds = 20; private boolean loadedFromZookeeper = false; public RemoteConfigWithCache(String name, String basePath, List paths, CuratorFramework client, File cacheFile) { super(name, basePath, paths, client); this.cacheFile = cacheFile; } public File getCacheFile() { return cacheFile; } public void setDelaySeconds(long delaySeconds) { this.delaySeconds = delaySeconds; } @Override public void start() { Set checking = Sets.newConcurrentHashSet(); //有本地配置就先从本地加载 if (cacheFile.exists()) { try { copyOf(Files.toByteArray(cacheFile)); //异步检查zookeeper中配置 checking.add(this); } catch (IOException e) { LOG.error("cannot read {}", cacheFile); initZookeeper(); } } else { //本地没有则直接从zookeeper加载 initZookeeper(); } //注册本地配置变更通知回调 FileUpdateWatcher.getInstance().watch(cacheFile.toPath(), new IFileListener() { @Override public void changed(Path path, byte[] content) { LOG.info("local change: {}", path); refresh(content); } }); //延迟加载zookeeper上的配置,避免服务启动过慢 asyncCheckZookeeper(checking); } private void asyncCheckZookeeper(final Set asyncCheck) { Thread zkThread = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(delaySeconds * 1000); } catch (InterruptedException ignored) { return; } for (RemoteConfig i : asyncCheck) { try { i.initZookeeper(); } catch (Exception e) { LOG.error("cannot init {}, cacheFile={}", i.getName(), getCacheFile(), e); } } asyncCheck.clear(); LOG.info("async load from zookeeper, DONE"); } }, "asyncLoadFromZookeeper"); zkThread.setDaemon(true); zkThread.start(); } private void refresh(byte[] content) { if (isChanged(content)) { copyOf(content); notifyListeners(); try { //已经加载过,就不要再通过本地文件修改通知再加载1次了 FileUpdateWatcher.getInstance().mask(cacheFile.toPath()); Files.write(content, cacheFile); } catch (IOException e) { LOG.error("cannot write {}", cacheFile); } } } @Override protected void reload(byte[] content) { //避免首次启动,远程配置不存在反而覆盖了本地配置 if ((content == null || content.length == 0) && !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