了解一下SseEmitter(一)

SseEmitter简介

Server-Sent Events 是HTTP协议中的一种,Content-Type为text/event-stream,能够保持长连接,简称Sse ,Emitter意为发射器,顾名思义,SseEmitter用于发送Server-Sent Events,一种服务器推送技术。

常见的服务器推送技术:
(1)长轮询:客户端向服务器发起一个长时间的请求,一直保持打开,直到服务器有新内容推送。效率不高但兼容性好。
(2)SSE(Server Sent Events):服务器可以在需要时一直向客户端推送事件,客户端只需要监听一个事件源。兼容性一般。
(3)WebSocket:基于TCP的双向通信,服务器和客户端建立持久连接,允许双向实时消息传输。兼容性差但效率高。

SSE只能发送文本消息,消息内包含:

消息内容说明
ID事件的 ID
事件事件类型
数据事件数据
重试事件流的重新连接时间

支持哪些功能?

  1. 能主动向单个客户端推送消息。与该客户端保持持久连接。通过此连接,服务器可以随时将事件推送给这个客户端。
  2. 支持推送不同类型的事件。客户端通过事件的名称能区分不同类型的事件,并作出不同的响应。
  3. 支持推送基本数据类型和POJO对象。服务器可以推送String、int等基本类型,也可以推送任意的Java对象。
  4. 能主动通知客户端关闭。通过调用complete()或error()方法,服务器可以主动告知客户端连接已关闭。

如何使用

在Spring MVC中可以很容易的实现.仅仅需要返回一个SseEmitter类型的值

  1. 同步返回一个建立的 SseEmitter 连接给客户端
  2. 异步线程中进行数据推送

示例代码:

		// 设置连接超时时间,也可以使用spring.mvc.async.request-timeout属性来限制异步请求的超时时间。
        final SseEmitter emitter = new SseEmitter(600_000L);  
        // 注册超时回调,超时后触发
        emitter.onTimeout(() -> {  
            logger.info("连接已超时,正准备关闭");   
        });  
        // 注册完成回调,调用 emitter.complete() 触发
        emitter.onCompletion(() -> {  
            logger.info("连接已关闭,正准备释放");  
        });  
        // 注册异常回调,调用 emitter.completeWithError() 触发
        emitter.onError(throwable -> {  
            logger.error("连接已异常,正准备关闭");  
        });  
        //Controller中直接返回SseEmitter,不调用complete()方法,即可保持长链接。
		return emitter; 
//向客户端发送消息,客户端连接关闭会触发onError和onCompletion回调
emitter.send("客户端接收文本");
//特有数据格式,本质还是个文本
//格式说明: sb.append("id:").append(id).append('\n').append("event:").append(name).append('\n')...;
emitter.send(SseEmitter.event()
                  .id("消息ID")
                  .name("消息名称")
                  .data("消息详情obj")
                  .data("消息详情obj", MediaType. APPLICATION_JSON)
                  //更改默认等待时间。服务端可以设置标志位为0,表示连接关闭则立即发起重试,没有等待时间
                  .reconnectTime("重连等待时间")
                  .comment("说明字段"))
//关闭连接
//推送数据结束后,不要在 finally 块中调用 emitter.complete() 来关闭连接,
//否则会触发一个很诡异的BUG,如果此时在很短的时间内请求别的接口,可能会收到一个502 bad Gateway 的异常信息,
//原因可参考:https://blog.youkuaiyun.com/sqlxx/article/details/121429478
emitter.complete();

与WebSocket对比

SseEmitterWebSocket
服务端主动将事件通过 HTTP 响应推送给客户端(只能被动接收)双向通信
经常建立和关闭连接建立后保持连接不断
原生支持的浏览器相对较少,需要Polyfill(一种代码或插件,用于为浏览器提供尚未支持的原生功能)大部分浏览器支持
文本文本以及二进制数据

拓展了解

响应式编程:https://cloud.tencent.com/developer/article/1497796?from_column=20421&from=20421

实现客户端与服务器端双向通信的方式:轮询(polling)、长轮询(long-polling)和iframe流(streaming)
(1)长轮询(long-polling):长轮询是对轮询的改进版。客户端发送HTTP给服务器之后,看有没有新消息,如果没有新消息,就一直等待(而不是一直去请求了)。当有新消息的时候,才会返回给客户端。 优点是对轮询做了优化,时效性也较好。缺点是:保持连接会消耗资源; 服务器没有返回有效数据,程序超时
(2)iframe流(streaming):是在页面中插入一个隐藏的iframe,利用其src属性在服务器和客户端之间创建一条长连接,服务器向iframe传输数据(通常是HTML,内有负责插入信息的javascript),来实时更新页面。
(3)WebSocket:WebSocket协议是基于TCP的一种新的网络协议。它实现了浏览器与服务器全双工(full-duplex)通信——允许服务器主动发送信息给客户端。它将TCP的Socket(套接字)应用在了webpage上。 优点:支持双向通信,实时性更强;可发送二进制文件;非常节省流量。 但也是有缺点的:浏览器支持程度不一致,不支持断开重连

参考文档:
https://juejin.cn/post/7250328942841495613
https://blog.youkuaiyun.com/lilinhai548/article/details/142095127
https://cloud.tencent.com/developer/article/1497804

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值