四中标色的代码

          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!

Nacos深入浅出(五)的更多相关文章

  1. Nacos深入浅出(十)

    基本上到第9篇,整个请求的一套就结束了,感觉这里跳跳绕绕很多东西,下面我们来做个总结:从Nacos配置平台修改,到Client请求更新,事件触发去取值返回给客户端,整个过程感觉只分析到了4.5层的深度 ...

  2. Nacos深入浅出(九)

    然而Nacos的发布操作并不是上面我们想的那样通过代理去实现,通过下面的代码我们分析下: public class NacosConfigurationPropertiesBindingPostPro ...

  3. Nacos深入浅出(八)

    Nacos-spring-context.java 感觉这个后台要比之前的Nacos复杂多了,涉及到很多基础的概念,慢慢看,这个后面慢慢更新解析过程 看到他的目录结构一个是基于注解,一个是XML的解析 ...

  4. Nacos深入浅出(七)

    大家可以把这个也下载下来,结合之前的Nacos一起来看下,感觉前面几篇看了好像冰山一角的感觉 学无止境! https://github.com/nacos-group/nacos-spring-pro ...

  5. Nacos深入浅出(六)

    其实我们发现在我们本地新生成了文件,这个文件就是nacos; 这个文件怎么那么眼熟,不就是我们的controller中的注解里面的参数value么: @Controller @NacosPropert ...

  6. Nacos深入浅出(四)

    private void executeAsyncInvoke() { while (!queue.isEmpty()) { NotifySingleTask task = queue.poll(); ...

  7. Nacos深入浅出(二)

    如果你的服务已经能正常跑起来,个人建议可以先感受下nacos的魅力,也就是怎么使用吧 直接上代码 @Controller @NacosPropertySource(dataId = "spr ...

  8. Nacos深入浅出(一)

    Nacos代码第一次给我的感觉有点小清新,下面就带大家抽丝剥茧看看源代码,看看阿里大神的东东: 建议大家先把Nacos跑起来,网上有很多教程,最好直接去git里面拉代码,在IDEA里面运行: cons ...

  9. Nacos(五):多环境下如何“读取”Nacos中相应的配置

    前言 前景回顾: Nacos(四):SpringCloud项目中接入Nacos作为配置中心 Nacos(三):Nacos与OpenFeign的对接使用 Nacos(二):SpringCloud项目中接 ...

随机推荐

  1. 《avascript 高级程序设计(第三版)》 ---第二章 在HTML中使用Javascript

    本章主要讲解了,怎么在HTML中使用: 1.<script src=""></script> 属性:defer="defer" 表示脚本 ...

  2. Warning: Cannot send session cookie – headers already sent…

    相信大多数人在写PHP代码的时候,都遇到过类似 "Warning: Cannot send session cookie – headers already sent…“或者”Cannot ...

  3. 9.1 NOIP普及组试题精解(3)

    9-6 seat.c #include <stdio.h> #define MAXN 1001 void swap(int *a, int *b) //交换数据 { int t; t = ...

  4. 基于node.js及express实现中间件,实现post、get

    首先,当然是有必要的环境,安装node,这个我就不多说了. 依赖模块: "express": "^4.13.4", "request": & ...

  5. What can I yield?

    浏览器支持情况:Enabled by default in desktop Chrome 39  一句话回答这个问题是:Promise,Thunks.为什么没有Generators?因为Generat ...

  6. Collaborative Index Embedding for Image Retrieval

    最近看了一篇比较好的文章,效果很好,简单记录一下. 这篇文章的核心思想是,融合两种不同类型的特征.文章中用的是SIFT和CNN提取的特征.还是神经大法好啊. 第一步就是建立两种不同特征的索引,文章用的 ...

  7. PS 滤镜— —图像偏移

    clc; clear all; close all; addpath('E:\PhotoShop Algortihm\Image Processing\PS Algorithm'); I=imread ...

  8. HDU5875Function(单调队列)

    The shorter, the simpler. With this problem, you should be convinced of this truth.      You are giv ...

  9. ESFramework Demo -- P2P通信Demo(附源码)

    现在我们将在ESFramework Demo -- 文件传送Demo 的基础上,使用ESPlus提供的第四个武器,为其增加P2P通信的功能.在阅读本文之前,请务必先掌握ESFramework 开发手册 ...

  10. linux——boot空间不足

    1. 先用df命令,查看磁盘分区情况 2. dpkg --get-selections|grep linux-image(查看更新了多少内核) root@ubuntu:/home/hadoop# dp ...