sse java_SSE详解
SSE(Server-Sent Events):通俗解释起来就是一种基于HTTP的,以流的形式由服务端持续向客户端发送数据的技术
应用场景
由于HTTP是无状态的传输协议,每次请求需由客户端向服务端建立连接,HTTPS还需要交换秘钥,所以一次请求,建立连接的过程占了很大比例
在http1.1中(1.0也有但未写入标准),虽然增加了keep-alive来保持和服务器的长连接,省去了很多建立连接的过程,但通信过程仍然是应答式1:1的方式,也就是想要获得数据,就必须先发送一个request才能得到一个response,所以在实时监控、推送、视频直播等实时性较高或者带宽利用较苛刻的场景,仍然不是很合适
SSE技术由于能保持连接,并持续接收服务端的数据,所以弥补了这一缺点,与其他类似技术方案相比,短轮询、Coment、WebSocket,在大多数时候,SSE仍然是最好的选择
各技术方案的优缺点
短轮询
短轮询很简单,即客户端定时的向服务端发送请求,如果服务端有数据返回,则返回数据,否则返回空数据
优点:实现简单
缺点:如果想实时性好,则必须轮询间隔短,但会有大量的请求是无效的(返回空数据),如果轮询间隔长,则实时性不好,数据到达客户端的延时最大会趋近于轮询间隔
Coment:一种HACK技术
以即时通信为代表的web应用程序对数据的Low Latency要求,传统的基于轮询的方式已经无法满足,而且也会带来不好的用户体验。于是一种基于http长连接的“服务器推”技术便被hack出来。这种技术被命名为Comet,这个术语由Dojo Toolkit 的项目主管Alex Russell在博文Comet: Low Latency Data for the Browser首次提出,并沿用下来。
Coment技术有两种实现,分别是长轮询(long-polling)和基于 Iframe 及 htmlfile 的流(http streaming)方式
1.长轮询(long-polling)
浏览器发出ajax 请求,服务器端接收到请求后,会阻塞请求直到有数据或者超时才返回,浏览器JS在处理请求返回信息(超时或有效数据)后再次发出请求,重新建立连接。在此期间服务器端可能已经有新的数据到达,服务器会选择把数据保存,直到重新建立连接,浏览器会把所有数据一次性取回。
优缺点:这种技术没有明显的优缺点,如果非要说,就是需要额外的框架支持吧,且在之前服务端异步编程支持程度并不高的时候,(例如java的servlet3.0之前),后端也需要额外的框架支持
2.基于 Iframe 及 htmlfile 的流
Iframe是html标记,这个标记的src属性会保持对指定服务器的长连接请求,服务器端则可以不停地返回数据,相对于第一种方式,这种方式跟传统的服务器推则更接近。
在第一种方式中,浏览器在收到数据后会直接调用JS回调函数,但是这种方式该如何响应数据呢?可以通过在返回数据中嵌入JS脚本的方式,如“”,服务器端将返回的数据作为回调函数的参数,浏览器在收到数据后就会执行这段JS脚本。
缺点:IE、Morzilla Firefox 下端的进度栏都会显示加载没有完成,而且 IE 上方的图标会不停的转动,表示加载正在进行。
WebSocket
类似TCP socket,参考WebSocket详解
优点:双工通信
缺点:需专门定义数据协议,解析数据流,且部分服务器支持不完善,后台例如java spring boot 2.1.2 仅支持websocket 1.0(最高已达1.3)
SSE
优点:开发简单,和传统的http开发几乎无任何差别,客户端开发简单,有标准支持(EventSource)
缺点:和websocket相比,只能单工通信,建立连接后,只能由服务端发往客户端,且占用一个连接,如需客户端向服务端通信,需额外打开一个连接
其他
在基于spring的开发中,可以使用SseEmitter类进行通信
@GetMapping(value = "/watch", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public synchronized SseEmitter watch(HttpServletRequest request, @RequestParam("point") String point) throws Exception {
final HttpSession session = request.getSession();
//此处超时时间优先级高于servlet容器的request timeout,PS:此超时时间固定,无法通过心跳等其他手段保持连接,超时后 浏览器端默认会重新连接,但SeeEmitter无法复用
SseEmitter emitter = new SseEmitter(300 * 1000L);
String key = String.format("watch:%s", point);
WatchConsumer consumer = new WatchConsumer<>(client, emitter, point);
if (this.client.watch(point, consumer)) {
emitter.onCompletion(() -> session.removeAttribute(key));
emitter.onTimeout(() -> session.removeAttribute(key));
emitter.onError(throwable -> {
throwable.printStackTrace();
session.removeAttribute(key);
});
session.setAttribute(key, consumer);
}
return emitter;
}
也可以利用WebFlux,
@GetMapping("/stream-sse")
public Flux> streamEvents() {
return Flux.interval(Duration.ofSeconds(1))
.map(sequence -> ServerSentEvent. builder()
.id(String.valueOf(sequence))
.event("periodic-event")
.data("SSE - " + LocalTime.now().toString())
.build());
}
但相比之下SseEmitter有OnTimeout和OnCompletion等事件,更加灵活
PS:由于浏览器对于同一个domain,有并发数限制,例如chrome最大是6,长连接会持续性的占用一个连接,同时会占用一个服务器端的一个连接
sse java_SSE详解相关推荐
- 【转】WebSocket详解(一):初步认识WebSocket技术
1.前言 HTML5规范在传统的web交互基础上为我们带来了众多的新特性,随着web技术被广泛用于web APP的开发,这些新特性得以推广和使用,而websocket作为一种新的web通信技术具有巨大 ...
- 新手入门:史上最全Web端即时通讯技术原理详解
前言 有关IM(InstantMessaging)聊天应用(如:微信,QQ).消息推送技术(如:现今移动端APP标配的消息推送模块)等即时通讯应用场景下,大多数都是桌面应用程序或者native应用较为 ...
- WebSocket详解(一):初步认识WebSocket技术
WebSocket详解(一):初步认识WebSocket技术 1.前言 HTML5规范在传统的web交互基础上为我们带来了众多的新特性,随着web技术被广泛用于web APP的开发,这些新特性得以推广 ...
- P2P技术详解(一):NAT详解——详细原理、P2P简介(转)
这是一篇介绍NAT技术要点的精华文章,来自华3通信官方资料库,文中对NAT技术原理的介绍很全面也很权威,对网络应用的应用层开发人员而言有很高的参考价值. <P2P技术详解>系列文章 ➊ 本 ...
- 015. P2P技术详解(一):NAT详解——详细原理、P2P简介
http://www.52im.net/thread-50-1-1.html 这是一篇介绍NAT技术要点的精华文章,来自华3通信官方资料库,文中对NAT技术原理的介绍很全面也很权威,对网络应用的应用层 ...
- (转)理论经典:TCP协议的3次握手与4次挥手过程详解
摘要: 本文将分别讲解经典的TCP协议建立连接(所谓的"3次握手")和断开连接(所谓的"4次挥手")的过程. 1.前言 尽管TCP和UDP都使用相同的网络层(I ...
- 新手入门贴:史上最全Web端即时通讯技术原理详解
前言 有关IM(InstantMessaging)聊天应用(如:微信,QQ).消息推送技术(如:现今移动端APP标配的消息推送模块)等即时通讯应用场景下,大多数都是桌面应用程序或者native应用较为 ...
- Web端即时通讯技术原理详解
Web端即时通讯技术原理详解 前言 在web端的IM即时通讯应用,由于浏览器的兼容性以及其固有的"客户端请求服务器处理并响应"的C/S通信模型,造成了要在浏览器中实现一个兼容性较好 ...
- Linux中/proc目录下文件详解
Linux中/proc目录下文件详解(一) 声明:可以自由转载本文,但请务必保留本文的完整性. 作者:张子坚 email:zhangzijian@163.com 说明:本文所涉及示例均在fedora ...
最新文章
- C#最基本的小说爬虫
- 文件服务器的配置与管理(2) 实现软RAID
- 因OpenCV版本不一致所引发的报错
- router锚点和html锚点,hash模式下Vue-router页面返回锚点(scroll behavior)实现
- Android studio gradle 无法获取 pom文件
- SpringBoot 使用 log4j2
- GP学习(二)—Executing tools and Accesubg licensing0
- 轻量版 markdown博客_如何快速搭建自己的博客平台
- Hadoop之自定义数据类型
- Cocos Creator 原生安卓改包名+AS运行到真机apk被slice处理而失败
- 【独家】阿里云罗庆超:对象存储 OSS 海量数据管理和应用最佳实践
- 蓝桥杯c语言b组试题及答案,2014蓝桥杯C语言本科B组预赛试题
- android web sevice,Web Service在Android开发中的应用研究
- Win10版本怎么转换?小编教你一键切换Windows版本
- JAVA高效批量插入数据到数据库demo
- 神经网络权重是什么意思,神经网络权重调整方法
- AJP:22q11.2缺失综合征青少年gamma频带反应和远程通信中断的异常发育模式
- 沉船会有什么_神秘沉船,惊人宝藏,尘封历史,这部纪录片的结尾却让人难以置信...
- 保障4-0601任务打卡
- [MachineLearning]模型评估与模型选择
热门文章
- expect java,Expect 使用详解
- 关于linux内核中jiffies和jiffies_64解析
- VSCode 根据需要设置自动补全(代码联想)类别
- pytest fixture简介
- 鸿蒙哪些机型可以用,鸿蒙系统可以在哪些手机上使用 鸿蒙系统升级名单
- Cell Biolabs丨艾美捷——细胞选择 24孔细胞共培养系统
- Presto客户端报错:Query failed (#20200815_082938_00004_a5yxe) in tmall-presto: Catalog hive does not exis
- 第7章 事件驱动编程:编写一个视频游戏
- 免费的IP地址查询API接口
- php编写六十甲子纳音表,六十花甲子纳音表