Dubbo-聊聊注册中心的设计( 五 )

缓存设计注册中心有两份缓存,一份在内存,一份在磁盘 。该方法的作用是将内存中的缓存数据保存在磁盘文件中,该方法有错误重试,最大重试次数是3,重试采用另一个线程去执行重试,不是当前线程 。本地缓存设计相当于是一种容错机制,当网络抖动等原因而导致订阅失败时,Consumer端的Registry就可以通过getCacheUrls()方法获取本地缓存,从而得到最近注册的服务提供者 。
    //将内存中的文件写到磁盘上    public void doSaveProperties(long version) {        //版本号判断 防止重复写        if (version < lastCacheChanged.get()) {            return;        }        //判断磁盘文件是否为空        if (file == null) {            return;        }        // Save        try {            //lock文件,用于加锁操作            File lockfile = new File(file.getAbsolutePath() + ".lock");            if (!lockfile.exists()) {                lockfile.createNewFile();            }            //RandomAccessFile提供对文件的读写操作            try (RandomAccessFile raf = new RandomAccessFile(lockfile, "rw");                 FileChannel channel = raf.getChannel()) {                //获取锁                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();                    }                    try (FileOutputStream outputFile = new FileOutputStream(file)) {                        //从内存缓存中获取数据 写入文件                        properties.store(outputFile, "Dubbo Registry Cache");                    }                } finally {                    lock.release();                }            }        } catch (Throwable e) {            //发生异常时,重试次数+1            savePropertiesRetryTimes.incrementAndGet();            //重试次数大于抛出异常            if (savePropertiesRetryTimes.get() >= MAX_RETRY_TIMES_SAVE_PROPERTIES) {                logger.warn("Failed to save registry cache file after retrying " + MAX_RETRY_TIMES_SAVE_PROPERTIES + " times, cause: " + e.getMessage(), e);                savePropertiesRetryTimes.set(0);                return;            }            //再次对比版本信息,如果版本已过期,返回不再处理            if (version < lastCacheChanged.get()) {                savePropertiesRetryTimes.set(0);                return;            } else {                //重试线程                registryCacheExecutor.execute(new SaveProperties(lastCacheChanged.incrementAndGet()));            }            logger.warn("Failed to save registry cache file, will retry, cause: " + e.getMessage(), e);        }    }    //磁盘中文件加载到内存中    private void loadProperties() {        if (file != null && file.exists()) {            InputStream in = null;            try {                in = new FileInputStream(file);                properties.load(in);                if (logger.isInfoEnabled()) {                    logger.info("Load registry cache file " + file + ", data: " + properties);                }            } catch (Throwable e) {                logger.warn("Failed to load registry cache file " + file, e);            } finally {                if (in != null) {                    try {                        in.close();                    } catch (IOException e) {                        logger.warn(e.getMessage(), e);                    }                }            }        }    }

经验总结扩展阅读