gongstring技术博客
最新文章
源码解读
软件安装
常见问题
大数据
常用工具
鸡汤文
备案号:鄂ICP备15015839号-1
鄂公网安备 42010202001692号
Dubbo提供者本地缓存配置源码解析
2018-06-15 14:22:40
作者: gongstring
源码解读
/
Dubbo提供者本地缓存配置源码解析
## 问题  根据官方图,dubbo调用者需要通过注册中心(例如:ZK)注册信息,获取提供者,但是如果频繁往ZK获取信息,肯定会存在单点故障问题,所以dubbo提供了将提供者信息缓存在本地的方法。 Dubbo调用者在连接ZK后,提供者列表是如何进行本地缓存的? ## 源码 com.alibaba.dubbo.registry.support.AbstractRegistry类 读取配置: ``` public AbstractRegistry(URL url) { setUrl(url); // Start file save timer //<------------------------此处用于配置是否将提供者缓存到本地,如果不配置,则默认为false syncSaveFile = url.getParameter(Constants.REGISTRY_FILESAVE_SYNC_KEY, false); String filename = url.getParameter(Constants.FILE_KEY, System.getProperty("user.home") + "/.dubbo/dubbo-registry-" + url.getParameter(Constants.APPLICATION_KEY) + "-" + url.getAddress() + ".cache"); File file = null; if (ConfigUtils.isNotEmpty(filename)) { file = new File(filename); if (!file.exists() && file.getParentFile() != null && !file.getParentFile().exists()) { if (!file.getParentFile().mkdirs()) { throw new IllegalArgumentException("Invalid registry store file " + file + ", cause: Failed to create directory " + file.getParentFile() + "!"); } } } this.file = file; loadProperties(); notify(url.getBackupUrls()); } .......省略很多代码 private void saveProperties(URL url) { if (file == null) { return; } try { StringBuilder buf = new StringBuilder(); Map
> categoryNotified = notified.get(url); if (categoryNotified != null) { for (List
us : categoryNotified.values()) { for (URL u : us) { if (buf.length() > 0) { buf.append(URL_SEPARATOR); } buf.append(u.toFullString()); } } } properties.setProperty(url.getServiceKey(), buf.toString()); long version = lastCacheChanged.incrementAndGet(); //<-----------如果开启了缓存,将会调用保存方法 if (syncSaveFile) { doSaveProperties(version); } else { registryCacheExecutor.execute(new SaveProperties(version)); } } catch (Throwable t) { logger.warn(t.getMessage(), t); } } public void doSaveProperties(long version) { if (version < lastCacheChanged.get()) { return; } if (file == null) { return; } // Save try { File lockfile = new File(file.getAbsolutePath() + ".lock"); if (!lockfile.exists()) { lockfile.createNewFile(); } RandomAccessFile raf = new RandomAccessFile(lockfile, "rw"); try { FileChannel channel = raf.getChannel(); try { FileLock lock = channel.tryLock(); if (lock == null) { throw new IOException("Can not lock the registry cache file " + file.getAbsolutePath() + ", ignore and retry later, maybe multi java process use the file, please config: dubbo.registry.file=xxx.properties"); } // Save try { if (!file.exists()) { file.createNewFile(); } FileOutputStream outputFile = new FileOutputStream(file); try { properties.store(outputFile, "Dubbo Registry Cache"); } finally { outputFile.close(); } } finally { lock.release(); } } finally { channel.close(); } } finally { raf.close(); } } catch (Throwable e) { if (version < lastCacheChanged.get()) { return; } else { registryCacheExecutor.execute(new SaveProperties(lastCacheChanged.incrementAndGet())); } logger.warn("Failed to save registry store file, cause: " + e.getMessage(), e); } } ``` Constants常量类中,定义了很多dubbo中配置需要的参数名信息。 Constants.REGISTRY_FILESAVE_SYNC_KEY 源码 ``` public static final String REGISTRY_FILESAVE_SYNC_KEY = "save.file"; ``` 默认配置文件本地缓存路径,代码如下: ``` String filename = url.getParameter(Constants.FILE_KEY, System.getProperty("user.home") + "/.dubbo/dubbo-registry-" + url.getParameter(Constants.APPLICATION_KEY) + "-" + url.getAddress() + ".cache"); File file = null; if (ConfigUtils.isNotEmpty(filename)) { file = new File(filename); if (!file.exists() && file.getParentFile() != null && !file.getParentFile().exists()) { if (!file.getParentFile().mkdirs()) { throw new IllegalArgumentException("Invalid registry store file " + file + ", cause: Failed to create directory " + file.getParentFile() + "!"); } } } this.file = file; ``` 上面配置文件读取的常量Key: Constants.FILE_KEY = "file"; doSaveProperties 方法中通过在本地利用文件锁实现配置信息占用的问题,所以如果本地有多个dubbo实例,使用默认值会出现冲突的情况。此时需要在dubbo配置中添加不同的dubbo.registry.file进行区分;否则会有如下日志提示: ``` Can not lock the registry cache file " + file.getAbsolutePath() + ", ignore and retry later, maybe multi java process use the file, please config: dubbo.registry.file=xxx.properties ```