config 客户端

ClientWorker#ClientWorker 

构造方法中启动定时任务

ClientWorker.LongPollingRunnable

长轮询的任务,在 run 方法的结尾,重新把任务加入到线程池

ClientWorker#checkUpdateDataIds

客户端把所监听配置的元数据信息(namespace, group, dataId, md5)上报给 server

config server 处理请求

ConfigController#listener
LongPollingService#addLongPollingClient

server 比较客户端传过来的 md5 值,如果有变化,马上返回已变化配置的元数据,否则延迟返回。server 使用了 servlet 3.0 的异步机制,用 ScheduledExecutorService 线程池来返回延时响应,

final AsyncContext asyncContext = req.startAsync();
asyncContext.setTimeout(0L);
scheduler.execute(new ClientLongPolling(asyncContext, clientMd5Map, ip, probeRequestSize, timeout, appName, tag));

使用 ClientLongPolling 封装了 AsyncContext,timeout 参数,通过 AsyncContext 可以获取 request 和 response,
在 ClientLongPolling 的 run 方法中,用 ScheduledExecutorService 执行定时任务。所有客户端的 ClientLongPolling 放在 allSubs 中,是一个 ConcurrentLinkedQueue。

// com.alibaba.nacos.config.server.service.LongPollingService.ClientLongPolling
public void run() {
asyncTimeoutFuture = scheduler.schedule(new Runnable() {
@Override
public void run() {
try {
getRetainIps().put(ClientLongPolling.this.ip, System.currentTimeMillis());
/**
* 删除订阅关系
*/
allSubs.remove(ClientLongPolling.this); if (isFixedPolling()) {
LogUtil.clientLog.info("{}|{}|{}|{}|{}|{}",
(System.currentTimeMillis() - createTime),
"fix", RequestUtil.getRemoteIp((HttpServletRequest)asyncContext.getRequest()),
"polling",
clientMd5Map.size(), probeRequestSize);
List<String> changedGroups = MD5Util.compareMd5(
(HttpServletRequest)asyncContext.getRequest(),
(HttpServletResponse)asyncContext.getResponse(), clientMd5Map);
if (changedGroups.size() > 0) {
sendResponse(changedGroups);
} else {
sendResponse(null);
}
} else {
LogUtil.clientLog.info("{}|{}|{}|{}|{}|{}",
(System.currentTimeMillis() - createTime),
"timeout", RequestUtil.getRemoteIp((HttpServletRequest)asyncContext.getRequest()),
"polling",
clientMd5Map.size(), probeRequestSize);
sendResponse(null);
}
} catch (Throwable t) {
LogUtil.defaultLog.error("long polling error:" + t.getMessage(), t.getCause());
} } }, timeoutTime, TimeUnit.MILLISECONDS); allSubs.add(this);
}

如果在定时任务执行时,监听的配置文件依然没有变化,server 则返回空文本给 client;

如果发生了配置变更,会由 DataChangeTask 发送变化的配置 id 给客户端,同时取消定时任务。

// com.alibaba.nacos.config.server.service.LongPollingService.DataChangeTask#run
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());
}
}

客户端获得变化的配置元数据后,重新拉取新的配置。

config 客户端有有 2 种缓存文件,failover 和 snapshot,从代码看,server 不可用时,一般使用 snapshot

servlet 异步处理:
https://www.cnblogs.com/davenkin/p/async-servlet.html

final AsyncContext asyncContext = req.startAsync();
asyncContext 可以获取 request 和 response,
asyncContext.complete();

nacos 使用 servlet 异步处理客户端配置长轮询的更多相关文章

  1. 三周,用长轮询实现Chat并迁移到Azure测试

    公司的OA从零开始进行开发,继简单的单点登陆.角色与权限.消息中间件之后,轮到在线即时通信的模块需要我独立去完成.这三周除了逛网店见爱*看动漫接兼职,基本上都花在这上面了.简单地说就是用MVC4基于长 ...

  2. 长轮询实现Chat并迁移到Azure测试

    长轮询实现Chat并迁移到Azure测试 公司的OA从零开始进行开发,继简单的单点登陆.角色与权限.消息中间件之后,轮到在线即时通信的模块需要我独立去完成.这三周除了逛网店见爱*看动漫接兼职,基本上都 ...

  3. 基于HTTP的长轮询简单实现

    Web客户端与服务器之间基于Ajax(http)的常用通信方式,分为短连接与长轮询. 短连接:客户端和服务器每进行一次HTTP操作,就建立一次连接,任务结束就中断连接. 在长轮询机制中,客户端像传统轮 ...

  4. 实现Comet(服务器推送)的两种方式:长轮询和http流

    Comet 是一种高级的Ajax技术,实现了服务器向页面实时推送数据的技术,应用场景有体育比赛比分和股票报价等. 实现Comet有两种方式:长轮询与http流 长轮询是短轮询的翻版,短轮询的方式是:页 ...

  5. Apollo 3 定时/长轮询拉取配置的设计

    前言 如上图所示,Apollo portal 更新配置后,进行轮询的客户端获取更新通知,然后再调用接口获取最新配置.不仅仅只有轮询,还有定时更新(默认 5 分钟一次).目的就是让客户端能够稳定的获取到 ...

  6. 网页实时聊天之js和jQuery实现ajax长轮询

    众所周知,HTTP协议是无状态的,所以一次的请求都是一个单独的事件,和前后都没有联系.所以我们在解决网页实时聊天时就遇到一个问题,如何保证与服务器的长时间联系,从而源源不段地获取信息. 一直以来的方式 ...

  7. Web 通信 之 长连接、长轮询(转)

    Web 通信 之 长连接.长轮询(long polling) 基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强 ...

  8. Web 通信 之 长连接、长轮询(long polling)

    基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性. 一.什么是长连接.长轮询? 用通俗易 ...

  9. Web 通信 之 长连接、长轮询(long polling)(转)

    基于HTTP的长连接,是一种通过长轮询方式实现"服务器推"的技术,它弥补了HTTP简单的请求应答模式的不足,极大地增强了程序的实时性和交互性. 一.什么是长连接.长轮询? 用通俗易 ...

随机推荐

  1. 2、Java调用C语言(JNative法)

    这个方法也是挺麻烦的…… 一.下载JNative.jar,把它放在你jdk下的\jre\lib\ext目录下 二.在 F:\MinGW\JNative 新建 Test.java: public cla ...

  2. idea解除版本控制

    解除版本控制删除两个文件: 1.idea中删除vcs.xml 2.在项目文件夹中删除.git 参考:https://blog.csdn.net/qq_37999340/article/details/ ...

  3. 简单的python笔试题

    1.输出九九乘法口诀 for i in range(1,10): for j in range(1,i+1): print('{}*{}={}'.format(j,i,i*j),end=' ') pr ...

  4. PyMySQL和MySQLdb的区别

      网上很多关于Scrapy存入MySQL的教程,都会发现又这么一个包的引入: import MySQLdb import MySQLdb.cursors 聪明的你或许已经算到,需要安装MySQLdb ...

  5. STM32 总线

    AHB,是Advanced High performance Bus的缩写,译作高级高性能总线,这是一种“系统总线”.AHB主要用于高性能模块(如CPU.DMA和DSP等)之间的连接.AHB 系统由主 ...

  6. 每日一蠢 .kettle 下的kettle.properties文件内配置的内容不能被识别

    昨天装封装好的ETL 工具  窝将环境变量中的KETTLE_HOME删除了, 结果 .kettle 下的kettle.properties文件内配置的内容不能被识别 can't parse argum ...

  7. noip考前抱佛脚 数论小总结

    exCRT 求解韩信点兵问题,常见的就是合并不同\(mod\). 先mo一发高神的板子 for(R i=2;i<=n;++i){ ll Y1,Yi,lcm=Lcm(p[i],p[1]); exg ...

  8. C++ GUI Qt4学习笔记07

    C++ GUI Qt4   qtc++scrollobject编程 事件(event)是由串口系统或者Qt自身产生的,用以响应所发生的各类事情.当用户按下或者松开键盘或者鼠标上的按键时,就可以产生一个 ...

  9. 【05】Python 标准模块:random、os、time、hashlib 第三方模块:excel、数据库 列表生成式

    1 模块分类 标准模块,不需要你单独安装,python自带的模块 第三方模块 自己写的python 一个python文件就是一个模块 2 random模块 2.1 随机取元素 import rando ...

  10. 初始化一个React项目

    1.create-react-app是一个通过npm发布的安装包,在确认Node.js和npm安装好之后,输入下面命令创建. 2.安装结束后,使用下面命令创建应用目录. 3.打开目录 4.运行项目 5 ...