点击下方“JavaEdge”,选择“设为星标”
第一时间关注技术干货!
免责声明~ 任何文章不要过度深思! 万事万物都经不起审视,因为世上没有同样的成长环境,也没有同样的认知水平,更「没有适用于所有人的解决方案」; 不要急着评判文章列出的观点,只需代入其中,适度审视一番自己即可,能「跳脱出来从外人的角度看看现在的自己处在什么样的阶段」才不为俗人。 怎么想、怎么做,全在乎自己「不断实践中寻找适合自己的大道」
Nacos 也是通过AsyncContext
实现长轮询机制来管理配置更新。
来观察下 Nacos#LongPollingService的源码实现,从中抄到并学习如何利用好长轮询机制。
![1 获取头信息和延迟时间](http://dingyue.ws.126.net/2024/0611/5ba87e46j00sevgm3003bd000u0008dc.jpg)
打开网易新闻 查看精彩图片
从请求头中获取长轮询相关的标识符和延迟时间信息:
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
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/ 专注分享软件开发全生态相关技术文章、视频教程资源、热点资讯等,全站资源免费学习,快来看看吧~
欢迎长按图片加好友
,我会第一时间和你分享软件行业趋势
,面试资源
,学习方法
等等。
添加好友备注【技术群交流】拉你进技术交流群
关注公众号后,在后台私信:
更多教程资源应有尽有,欢迎
关注并加技术交流群,慢慢获取
热门跟贴