四中标色的代码

          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. HDU 2138 How many prime numbers(Miller_Rabin法判断素数 【*模板】 用到了快速幂算法 )

    How many prime numbers Time Limit: 3000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/O ...

  2. 一篇文章教你如何用R进行数据挖掘

    一篇文章教你如何用R进行数据挖掘 引言 R是一种广泛用于数据分析和统计计算的强大语言,于上世纪90年代开始发展起来.得益于全世界众多 爱好者的无尽努力,大家继而开发出了一种基于R但优于R基本文本编辑器 ...

  3. IE不支持HTML5表单属性placeholder的解决办法

    1. [代码][JavaScript]代码 (function ($) {    $.fn.placeholder = function (options) {        var defaults ...

  4. 粉红色织梦CMS企业模板

    粉红色织梦CMS企业网站模板,粉红色,织梦CMS,织梦企业模板,CMS模板. 模板地址:http://www.huiyi8.com/sc/7247.html

  5. struts2 自定义类型转化 第三弹

    1.Struts2的类型转化,对于8种原生数据类型以及Date,String等常见类型,Struts2可以使用内建的类型转化器实现自动转化:但对于自定义的对象类型来说,就需要我们自己指定类型转化的的方 ...

  6. html5--2.1新的布局元素概述

    html5--2.1新的布局元素概述 学习要点 了解HTML5新标签(元素)的优点 了解本章要学习的新的布局元素 了解本章课程的安排 HTML5新标签的优点: 更注重于内容而不是形式 对人的友好:更加 ...

  7. html5--1.7超链接上

    html5--1.7超链接上 一.超链接的5种形式 <!DOCTYPE html> <html lang="en"> <head> <me ...

  8. AOP和IOC的作用(转)

    AOP和IOC的作用 转载▼     IOC:控制反转,是一种设计模式.一层含义是控制权的转移:由传统的在程序中控制依赖转移到由容器来控制:第二层是依赖注入:将相互依赖的对象分离,在spring配置文 ...

  9. 开机时遇到grub rescue无法进入系统的解决方法

    装双系统(win10和elementary os),elementary os是ubuntu的一个分支.在win10中合并了一块空白磁盘分区,再开机的时候出问题了. 遇到filesystem unkn ...

  10. 跨线程send message

    今天同事问了一个问题,说在线程中send message 和直接调用是不是一样,他觉得是一样的,但是线程跟踪却发现处理过程是在接收消息队列完成.回家看到博客园上的一番争论才有些明白,这里贴出来,共勉 ...