四中标色的代码

          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. 最全面的HashMap和HashTable的区别

    找工作期间不少企业都会问到有关HashMap和HashTable两者直接的区别,很多博客里虽然有提及但总是没有那么全面,只是一些常用的不同,现在就我自己所总结的比较全面的不同,归纳以下: HashMa ...

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

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

  3. 9.2 NOIP提高组试题精解(1)

    9-16 poise.c #include <stdio.h> #define MAXN 1001 int main() { ], flag[MAXN] = { }; //保存6种砝码的数 ...

  4. JAVA- continue与break与return关键字

    continue与break关键字 for(int i=0;i<10;i++){ if(i%2==0){ continue; //跳过当前循环执行下一次循环 } System.out.print ...

  5. 标准兼容HTML5输入框提示信息的插件iHolder_v0.1.06.21.2014_预览版

    由于版面限制,简单说下,详细的内容及在线预览.预览版压缩包,见这里http://levi.cg.am/archives/3507 为什么说是标准兼容: 因为大多数placeholder插件是这样兼容的 ...

  6. Cocos2d-x中判断点击是否在触摸屏区域

    新建2dx工程. 在HelloWorld头文件加入以下语句: virtual void registerWithTouchDispatcher();//注册触屏事件 覆写register方法 virt ...

  7. 使用top命令查看系统状态

    Linux系统可以通过top命令查看系统的CPU.内存.运行时间.交换分区.执行的线程等信息.通过top命令可以有效的发现系统的缺陷出在哪里.是内存不够.CPU处理能力不够.IO读写过高? 使用SSH ...

  8. codeforces 610D D. Vika and Segments(离散化+线段树+扫描线算法)

    题目链接: D. Vika and Segments time limit per test 2 seconds memory limit per test 256 megabytes input s ...

  9. BZOJ_3935_Rbtree

    https://lydsy.com/JudgeOnline/problem.php?id=3935 分析: 如果知道更改后的状态,那么代价和是否合法都能求出来 对不合法的情况也设一个估价函数. 随机这 ...

  10. 人工智能实践:TensorFlow 框架

    张量.计算图.会话 基本概念 基于Tensorflow的NN:用张量表示数据,用计算图搭建神经网络,用会话执行计算图,优化线上的权重(参数),得到模型. 张量(Tensor):张量就是多维数组(列表) ...