点击下方“JavaEdge”,选择“设为星标”
第一时间关注技术干货!
免责声明~
任何文章不要过度深思!
万事万物都经不起审视,因为世上没有同样的成长环境,也没有同样的认知水平,更「没有适用于所有人的解决方案」;
不要急着评判文章列出的观点,只需代入其中,适度审视一番自己即可,能「跳脱出来从外人的角度看看现在的自己处在什么样的阶段」才不为俗人。
怎么想、怎么做,全在乎自己「不断实践中寻找适合自己的大道」
Nacos 也是通过 AsyncContext
实现长轮询机制来管理配置更新。
来观察下 Nacos#LongPollingService的源码实现,从中抄到并学习如何利用好长轮询机制。
1 获取头信息和延迟时间
从请求头中获取长轮询相关的标识符和延迟时间信息:
public static final String LONG_POLLING_HEADER = "Long-Pulling-Timeout";public static final String LONG_POLLING_NO_HANG_UP_HEADER = "Long-Pulling-Timeout-No-Hangup";String str = req.getHeader(LongPollingService.LONG_POLLING_HEADER);
String noHangUpFlag = req.getHeader(LongPollingService.LONG_POLLING_NO_HANG_UP_HEADER);
int delayTime = SwitchService.getSwitchInteger(SwitchService.FIXED_DELAY_TIME, 500);
2 计算超时时间
如用固定轮询间隔,则设置一个固定超时时间(最小10s)。
否则,计算一个基于请求头中提供的超时时间减去延迟时间的超时值:
long timeout = -1L;
if (isFixedPolling()) {timeout = Math.max(10000, getFixedPollingInterval());
} else {timeout = Math.max(10000, Long.parseLong(str) - delayTime);
}
3 检测配置变更
通过 MD5Util.compareMd5
比较客户端的MD5和服务器的MD5,判断配置是否变化:
long start = System.currentTimeMillis();
List<String> changedGroups = MD5Util.compareMd5(req, rsp, clientMd5Map);
if (changedGroups.size() > 0) {generateResponse(req, rsp, changedGroups);LogUtil.CLIENT_LOG.info("{}|{}|{}|{}|{}|{}|{}", System.currentTimeMillis() - start, "instant",RequestUtil.getRemoteIp(req), "polling", clientMd5Map.size(), probeRequestSize,changedGroups.size());return;
} else if (noHangUpFlag != null && noHangUpFlag.equalsIgnoreCase(TRUE_STR)) {LogUtil.CLIENT_LOG.info("{}|{}|{}|{}|{}|{}|{}", System.currentTimeMillis() - start, "nohangup",RequestUtil.getRemoteIp(req), "polling", clientMd5Map.size(), probeRequestSize,changedGroups.size());return;
}
4 连接限制检查
检查当前请求是否超过限制,是,则返回503响应:
String ip = RequestUtil.getRemoteIp(req);
ConnectionCheckResponse connectionCheckResponse = checkLimit(req);
if (!connectionCheckResponse.isSuccess()) {generate503Response(req, rsp, connectionCheckResponse.getMessage());return;
}
5 启动异步上下文
使用 AsyncContext
启动异步处理,防止 HTTP 线程阻塞,并设置超时时间为0(不超时):
final AsyncContext asyncContext = req.startAsync();
asyncContext.setTimeout(0L);
6 创建和提交长轮询任务
创建 ClientLongPolling
实例,并将其提交到定时线程池中执行:
String appName = req.getHeader(RequestUtil.CLIENT_APPNAME_HEADER);
String tag = req.getHeader("Vipserver-Tag");
ConfigExecutor.executeLongPolling(new ClientLongPolling(asyncContext, clientMd5Map, ip, probeRequestSize, timeout, appName, tag));
7 结论
Nacos 也是通过Servlet3.0 新增的 AsyncContext
实现长轮询机制,来处理配置更新。
当客户端发起长轮询请求时,服务器会异步等待配置变更或超时,若:
检测到配置变更,服务器立即响应客户端
没有变更,服务器会在预定的超时时间内保持连接
实际的长轮询处理中,通过将请求处理从主线程分离出来,Nacos 可以有效地处理大量的长轮询请求而不阻塞服务器线程,提高系统的可扩展性和响应效率。
写在最后
编程严选网:
http://www.javaedge.cn/
专注分享软件开发全生态相关技术文章
、视频教程
资源、热点资讯等,全站资源免费学习,快来看看吧~
欢迎长按图片加好友
,我会第一时间和你分享软件行业趋势
,面试资源
,学习方法
等等。
添加好友备注【技术群交流】拉你进技术交流群
关注公众号后,在后台私信:
回复【架构师】,获取架构师学习资源教程
回复【面试】,获取最新最全的互联网大厂面试资料
回复【简历】,获取各种样式精美、内容丰富的简历模板
回复 【路线图】,获取直升Java P7技术管理的全网最全学习路线图
回复 【大数据】,获取Java转型大数据研发的全网最全思维导图
更多教程资源应有尽有,欢迎
关注并加技术交流群,慢慢获取