随着 Web 应用程序的不断发展,前端开发已经成为了一个广受关注的领域。而 Server-Sent Events(SSE)是一项从服务器向客户端推送事件的技术,与 WebSocket 不同,SSE 只支持服务器推送。
在本文中,我们将探讨 SSE 与持久化连接及解决服务器负载等问题相关的内容。
持久化连接的实现
在传统的 HTTP 协议模型中,客户端向服务器发送一个请求,服务器返回一个响应,然后连接就会断开。这样的请求和响应模型不能满足实时通信的需求。
SSE 利用了浏览器支持长轮询 long-polling 机制,实现了服务器和客户端的持久化连接。
SSE 的持久化连接建立在单一的 HTTP 连接上。客户端通过一次 HTTP 连接,在服务器响应消息前,保持连接处于打开状态。
这样一来,服务器就可以利用已经打开的连接不断地向客户端推送消息了。如果连接因为某些原因断开,就重新发起一个连接。这个连接一直处于打开状态,直到服务器端明确要求关闭。
解决服务器负载等问题
在实际应用中,如果使用 SSE 的话,也会遇到一些问题。如:连接中断、失效处理等。
为解决这些问题,我们可以增加一些控制机制来优化 SSE 的使用。
1. 保持连接的活跃状态
客户端需要定时向服务器发送一个心跳包,以保持连接的活跃状态。如果一个连接长时间没有任何数据传输,很容易被中间层断开。这时候,客户端就需要重新发起请求,服务器也需要重新处理,并存储客户端的请求。
2. 断线重连
SSE 在多个点位上都有可能出现连接断开的情况,如服务器繁忙、网络不稳定等,存在一定的不稳定性。为了保证稳定的 SSE 体验,我们需要考虑断线重连逻辑。
断线重连逻辑主要有以下两个步骤:
- 重新连接服务器,并保持之前的组流名称;
- 优雅地关闭流(注:流的生命周期后面详细讲),避免产生大量的无效请求。
3. 保持消息的有序性
保持客户端消息的有序性是一个重要的问题,因为 SSE 中事件及数据具有一定的时序性。客户端收到的消息及事件应该与服务器依据业务需求的逻辑保持高度一致,并保证消息的有序性。
保证 SSE 中事件的有序性可以通过客户端定义的 last-event-id 字段来实现(注:接下来会详细讲)。客户端会通过请求头的 Last-Event-Id 的值来请求上次的事件数据。并且事件分为必须事件和持久性事件。必须事件的数据,在客户端连接到新流时,必须传递给满足事件名相应匹配的事件监听器。持久性事件的数据应该被保存下来,并在客户端连接到新流时重新传递。
示例代码
下面我们通过一段代码来演示 SSE 的用法:
-- -------------------- ---- ------- --- ------ - --- ----------------------- ------------- - -------- ------- - ----------------------- -------- -- ---------------- - -------- ------- - ------------------------ -- -------------- - -------- ------- - -- ----------------- -- ------------------- - ----------------------- ---------- - ---- - ----------------- ----- ----- ------------ - --展开代码
我们通过 new 一个 EventSource 对象,来实现与后端服务的持久化连接。以 stream(里面可以是我们写的一个长连接或 websocket)为地址,监听连接打开、收到消息、连接断开事件,并打印相关的信息。
SSE 虽然只支持服务器推送,但对于一些应用场景而言,它比任何其他的 WebSocket 方案都更加适合,如实时消息推送、在线直播等等。
总结
本文通过介绍 SSE 的持久化连接及服务器负载等问题解决方法,从技术角度分析了 SSE 背后所蕴含的机制和流程,在实践过程中能够更好地运用 SSE 知识。SSE 虽然有些局限性,但是在实际场景中具有不可替代的优越性,它的应用也越来越广泛。
笔者在此建议,为了更好地将 SSE 应用于实践中,开发人员应该深入了解 SSE 技术,做好 SSE 这项技术的支持工作。
来源:JavaScript中文网 ,转载请注明来源 https://www.javascriptcn.com/post/64e1f5f8f6b2d6eab3d468b3