什么是服务器发送事件(SSE)?它有什么好处?

什么是服务器发送事件(SSE)?

服务器发送事件(SSE)是一种基于 HTTP 协议的单向通信协议,它允许服务器以事件流(Event Stream)的形式实时向客户端推送数据,而无需客户端明确请求。它建立在标准的 HTTP 协议之上,通过单向的持久连接,服务器可以主动向客户端发送事件和数据。

Server-Sent Events

本质上,它是以流信息的方式来实现的,由客户端向服务端发起建立连接请求,并保持连接打开,然后服务端主动推送消息给客户端,服务器给客户端发送的 SSE 数据,必须是 UTF-8 编码,且返回的内容类型是 text/event-stream。

比如当你在使用 ChatGPT 时,当你询问它问题时,你会看到它会逐字地将回答显示出来,实际上这是 ChatGPT 将先计算出的数据主动的“推送”给你,采用 SSE 技术边计算边返回,避免接口等待时间过长而直接关闭页面。

Example of server-sent events

SSE 的优势

  1. 实时性:SSE 提供了一种实时通信机制,允许服务器主动向客户端推送数据。这种实时性使得 SSE 特别适用于需要即时更新的应用场景,如实时聊天、在线协作工具、实时数据展示、通知推送等。

  2. 减少网络负担:与传统的轮询方式相比,SSE 采用长连接,通过单一的 HTTP 连接,服务器可以向客户端推送多个事件,避免了频繁的 HTTP 请求,从而减少了网络负担。

  3. 轻量级:SSE 是基于 HTTP 协议,现有的服务器软件都支持,相较于 WebSocket,SSE 的使用更加简单。

  4. 自动重连:SSE 在连接中断后能够自动尝试重新建立连接,而无需额外的代码。这种自动重连机制增加了系统的稳定性,确保即使在网络不稳定的情况下,通信仍能够持续进行。

使用 API7 企业版网关代理 SSE 服务

在实际应用中,利用 API 网关代理 SSE 服务有助于提升服务的稳定性,解决安全和跨域问题,适用于处理复杂的应用场景。NGINX 作为最受欢迎的反向代理服务器之一,市场份额颇高。在 NGINX 上代理 SSE 服务时,需要禁用 proxy_buffering。然而,这种配置至少要在 location 级别进行关闭,这意味着如果系统中存在多个 location,仅有少数需要关闭缓存以支持 SSE 服务时,可能会影响其他非 SSE 的 API 的性能。此外,NGINX 的 proxy_buffering 配置缺乏灵活性,无法在运行时动态启用或禁用,需要通过重新加载配置来生效,这可能会导致服务中断。

API7 企业版提供了 proxy-buffering 插件,让您能更灵活地代理 SSE 上游服务。通过在相应的路由中启用该插件,您可以轻松控制缓存的开关,而无需重新加载整个配置。这种灵活性既能满足 SSE 服务的代理需求,又兼顾性能和动态配置的要求。

SSE plugin of API7 Enterprise

通过测试可以看到已经成功代理了 SSE 服务。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
curl "http://127.0.0.1:9080/.sse" -H "Accept: text/event-stream"

event: server
data: 27d365b177ae
id: 1

event: request
data: GET /.sse HTTP/1.1
data:
data: Host: 127.0.0.1:9080
data: Accept: text/event-stream
data: User-Agent: curl/8.1.2
data: X-Forwarded-For: 192.168.65.1
data: X-Forwarded-Host: 127.0.0.1
data: X-Forwarded-Port: 9080
data: X-Forwarded-Proto: http
data: X-Real-Ip: 192.168.65.1
data:
id: 2

event: time
data: 2024-01-29T04:04:20Z
id: 3

event: time
data: 2024-01-29T04:04:21Z
id: 4
...

总结

总体而言,SSE 适用于需要实时通信和更新的场景,它提供了一种简单而有效的方式。但是需要注意 SSE 是一种单向通道,只能由服务器向客户端发送消息,所以 SSE 并不适用于所有类型的实时通信需求。对于更复杂的双向通信场景,可以考虑使用 WebSocket 等其他技术。