SSE类似于HTTP,客户端通过请求向客户端注册SSE的请求,new SseEmitter()则代表请求成功,可以通过SseEmitter.event().data("连接成功")向浏览器指定的event(默认为data)发送信息。
java
@GetMapping(path = "/subscribe/{id}") public SseEmitter subscribe(@PathVariable("id") String id) throws IOException { if (StringUtil.isEmpty(id)) { return null; } SseEmitter sseEmitter; SseEmitter getClientEmitter = sseCache.get(id); if (getClientEmitter == null || !checkSseConnectAlive(getClientEmitter)) { // 持久生存 sseEmitter = new SseEmitter(0L); // 设置前端的重试时间 try { sseEmitter.send(SseEmitter.event().data("连接成功")); sseCache.put(id, sseEmitter); System.out.println("add " + id); sseEmitter.onTimeout(() -> { System.out.println(id + "超时"); sseCache.remove(id); }); sseEmitter.onCompletion(() -> System.out.println("已关闭连接:" + id)); } catch (Exception e) { System.err.println(e.getMessage()); } } else { System.out.println("已存在!"); sseEmitter = getClientEmitter; } return sseEmitter; }
在这个例子中,首先我们定义了一个名为/subscribe的URL,当客户端访问这个URL时,服务器会返回一个新的SseEmitter对象。
SSE的优点不仅在于其简单易用和实时性,还体现在其可靠性上。如果网络中断,SSE会自动尝试重新连接。一旦连接恢复,服务器就可以继续向客户端发送更新。
然而,SSE也有一些缺点需要注意。首先是浏览器兼容性问题,尽管大多数现代浏览器都支持SSE,但是一些旧版本的浏览器,如IE9及更早版本,不支持此功能。其次,由于SSE需要保持长连接,这可能会消耗大量的服务器资源,特别是在高并发情况下。
总的来说,Server-Sent Events是一种强大而实用的实现实时通信的技术。如果你正在开发需要实时更新的应用程序,并且对浏览器兼容性和服务器资源有一定的控制能力,那么SSE绝对值得你考虑。
协议方式 | HTTP | SSE | WebSocket |
通信方式 | 单向通信 浏览器 → 服务器 | 单向通信 浏览器 ← 服务器 | 双向通信 浏览器 ↔服务器 |
长连接 | 否 | 是 | 是 |
实时性 | 否 | 是 | 是 |
适用场景 | 浏览器请求,加载网页,提交数据 | 推送消息,消息提醒,时间推送 | 网络聊天 |
Server-Sent Events (SSE) 和 HTTP 是两种不同的通信协议,它们在实现客户端和服务器之间的数据传输时有各自的优点和适用场景。下面是 SSE 和 HTTP 的一些对比:
HTTP
- 单向通信:HTTP 是一种单向请求-响应协议。客户端发起一个请求,服务器响应这个请求,然后连接关闭。
- 非持久性连接:每次请求结束后,HTTP 连接都会被关闭。如果需要连续更新,客户端需要不断发起新的请求。
- 实时性较差:由于 HTTP 需要客户端轮询服务器以获取更新,这使得其不适合实时性要求较高的应用。
Server-Sent Events (SSE)
- 双向通信:SSE 允许服务器主动将数据推送到客户端,而不仅仅是响应客户端的请求。
- 持久性连接:一旦建立 SSE 连接,它会保持打开状态,直到客户端或服务器选择断开连接。
- 实时性强:由于服务器可以主动推送更新,SSE 适合实时性要求较高的应用,如股票报价、聊天应用等。
比较与总结
- HTTP 更适用于一次性请求和响应的情况,例如加载网页内容或提交表单数据。
- SSE 更适用于需要持续更新的应用,比如新闻流、聊天室或者动态图表的数据更新。
然而,这两种协议并不是互斥的。实际上,在许多情况下,它们会被结合使用,以便充分利用各自的优势。例如,一个应用程序可能会用 HTTP 来加载初始页面,然后用 SSE 来提供实时更新。
在Tomcat中配置了一个连接超时时间connectionTimout,如果在这个时间之后客户端不还未得到服务器端的响应,就会主动断开连接,产生上述异常,Tomcat中默认超时时间是20秒,我们一般设置为60秒,从而避免后台程序处理时间太长导致断开连接。