zoukankan      html  css  js  c++  java
  • Nacos深入浅出(五)

    四中标色的代码

              result = ConfigService.dump(dataId, group, tenant, cf.getContent(), lastModified);

    我们看下这个方法

      /**
         * 保存配置文件,并缓存md5.
         */
        static public boolean dump(String dataId, String group, String tenant, String content, long lastModifiedTs) {
            String groupKey = GroupKey2.getKey(dataId, group, tenant);
            makeSure(groupKey);
            final int lockResult = tryWriteLock(groupKey);
            assert (lockResult != 0);
    
            if (lockResult < 0) {
                dumpLog.warn("[dump-error] write lock failed. {}", groupKey);
                return false;
            }
    
            try {
                final String md5 = MD5.getInstance().getMD5String(content);
                if (md5.equals(ConfigService.getContentMd5(groupKey))) {
                    dumpLog.warn(
                        "[dump-ignore] ignore to save cache file. groupKey={}, md5={}, lastModifiedOld={}, "
                            + "lastModifiedNew={}",
                        groupKey, md5, ConfigService.getLastModifiedTs(groupKey), lastModifiedTs);
                } else if (!STANDALONE_MODE || PropertyUtil.isStandaloneUseMysql()) {
                    DiskUtil.saveToDisk(dataId, group, tenant, content);
                }
                updateMd5(groupKey, md5, lastModifiedTs);
                return true;
            } catch (IOException ioe) {
                dumpLog.error("[dump-exception] save disk error. " + groupKey + ", " + ioe.toString(), ioe);
                if (ioe.getMessage() != null) {
                    String errMsg = ioe.getMessage();
                    if (NO_SPACE_CN.equals(errMsg) || NO_SPACE_EN.equals(errMsg) || errMsg.contains(DISK_QUATA_CN)
                        || errMsg.contains(DISK_QUATA_EN)) {
                        // 磁盘写满保护代码
                        fatalLog.error("磁盘满自杀退出", ioe);
                        System.exit(0);
                    }
                }
                return false;
            } finally {
                releaseWriteLock(groupKey);
            }
        }

    这里MD5加密的意义就体现出来了,如果content的值没有变,这不需要激活

    LocalDataChangeEvent,不然则激活,这里又是另一个天地了;也是我们感兴趣的地方,go!
     public static void updateMd5(String groupKey, String md5, long lastModifiedTs) {
            CacheItem cache = makeSure(groupKey);
            if (cache.md5 == null || !cache.md5.equals(md5)) {
                cache.md5 = md5;
                cache.lastModifiedTs = lastModifiedTs;
                EventDispatcher.fireEvent(new LocalDataChangeEvent(groupKey));
            }
        }

    这个LocalDataChangeEvent比较简单,大家简单的过下,

    public class LocalDataChangeEvent implements Event {
        final public String groupKey;
        final public boolean isBeta;
        final public List<String> betaIps;
        final public String tag;
    
        public LocalDataChangeEvent(String groupKey) {
            this.groupKey = groupKey;
            this.isBeta = false;
            this.betaIps = null;
            this.tag = null;
        }
    
        public LocalDataChangeEvent(String groupKey, boolean isBeta, List<String> betaIps) {
            this.groupKey = groupKey;
            this.isBeta = isBeta;
            this.betaIps = betaIps;
            this.tag = null;
        }
    
        public LocalDataChangeEvent(String groupKey, boolean isBeta, List<String> betaIps, String tag) {
            this.groupKey = groupKey;
            this.isBeta = isBeta;
            this.betaIps = betaIps;
            this.tag = tag;
        }
    }

    我们主要看这个fireEvent里面的这个onEvent是如何处理的,上代码

    LongPollingService.java
     @Override
        public void onEvent(Event event) {
            if (isFixedPolling()) {
                // ignore
            } else {
                if (event instanceof LocalDataChangeEvent) {
                    LocalDataChangeEvent evt = (LocalDataChangeEvent)event;
                    scheduler.execute(new DataChangeTask(evt.groupKey, evt.isBeta, evt.betaIps));
                }
            }
        }

    DataChangeTask这个类,看看他的庐山真面目!

     class DataChangeTask implements Runnable {
            @Override
            public void run() {
                try {
                    ConfigService.getContentBetaMd5(groupKey);
                    for (Iterator<ClientLongPolling> iter = allSubs.iterator(); iter.hasNext(); ) {
                        ClientLongPolling clientSub = iter.next();
                        if (clientSub.clientMd5Map.containsKey(groupKey)) {
                            // 如果beta发布且不在beta列表直接跳过
                            if (isBeta && !betaIps.contains(clientSub.ip)) {
                                continue;
                            }
    
                            // 如果tag发布且不在tag列表直接跳过
                            if (StringUtils.isNotBlank(tag) && !tag.equals(clientSub.tag)) {
                                continue;
                            }
    
                            getRetainIps().put(clientSub.ip, System.currentTimeMillis());
                            iter.remove(); // 删除订阅关系
                            LogUtil.clientLog.info("{}|{}|{}|{}|{}|{}|{}",
                                (System.currentTimeMillis() - changeTime),
                                "in-advance",
                                RequestUtil.getRemoteIp((HttpServletRequest)clientSub.asyncContext.getRequest()),
                                "polling",
                                clientSub.clientMd5Map.size(), clientSub.probeRequestSize, groupKey);
                            clientSub.sendResponse(Arrays.asList(groupKey));
                        }
                    }
                } catch (Throwable t) {
                    LogUtil.defaultLog.error("data change error:" + t.getMessage(), t.getCause());
                }
            }
    
            DataChangeTask(String groupKey) {
                this(groupKey, false, null);
            }
    
            DataChangeTask(String groupKey, boolean isBeta, List<String> betaIps) {
                this(groupKey, isBeta, betaIps, null);
            }
    
            DataChangeTask(String groupKey, boolean isBeta, List<String> betaIps, String tag) {
                this.groupKey = groupKey;
                this.isBeta = isBeta;
                this.betaIps = betaIps;
                this.tag = tag;
            }
    
            final String groupKey;
            final long changeTime = System.currentTimeMillis();
            final boolean isBeta;
            final List<String> betaIps;
            final String tag;
        }

     到这里感觉好像还是没看到究竟是在哪变了,奇怪哦,咱们继续想办法,既然跟代码没跟出什么名堂,我不妨停下来想想?

    1、client在请求处理nacos参数的时候调用什么rpc服务,用的是返回的value么?

    2、如果没有请求的话 数据无非就几种载体,DB,cache,file

    DB不可能,我们的业务库根本就没有创建过相应的存储表,所以pass;

    cache也不可能,我们重启服务之后,数据还是在的,所以呢,肯定就是file了,会不会像我们的property一样,存在某个地方,然后按照一定的规则去取值,

    是不是?继续往下走,goo!

  • 相关阅读:
    【jQuery插件】使用cropper实现简单的头像裁剪并上传
    Hibernate与 MyBatis的比较
    ES引擎原理介绍
    ES中的分词器研究
    服务转发Feign
    hytrix的python实现
    Consul的服务注册与发现-python版本
    setupTools工具新建项目
    docker系统学习
    NLP关键技术
  • 原文地址:https://www.cnblogs.com/longxok/p/11016103.html
Copyright © 2011-2022 走看看