Din
Din
发布于 2024-06-01 / 11 阅读
0
0

使用SSE实时推送消息

背景

最近CRM系统有一个业务需求,需要将公海满足条件的线索,实时的推送到销售工作台。根据以往的经验,第一时间想到WebSocket。通过调研发现,有一种更轻量级的方式SSE,据了解,ChatGPT早起的版本也是使用的SSE技术

什么是SSE

SSE 是一种单向的、基于 HTTP 的服务器推送技术。它允许服务器通过一个长连接,单方面地向客户端推送数据流。与传统的请求-响应模式不同,SSE 建立连接后,服务器可以主动地持续地向客户端发送更新,而客户端无需不断轮询服务器。

SSE 基于 HTTP 协议,并以文本流的方式传递数据,使用的是标准的 text/event-stream MIME 类型。浏览器内置支持 SSE,无需额外的第三方库支持。

SSE 的工作原理

SSE 的工作流程主要包括以下几个步骤:

  1. 客户端发起连接请求: 客户端通过 JavaScript 或其他方式,向服务器发送一个 HTTP GET 请求,并在请求头中设置 Accept: text/event-stream,告知服务器客户端希望建立 SSE 连接。

  2. 服务器建立长连接并发送响应: 服务器收到请求后,会返回一个 HTTP 响应,响应头中包含:

    • Content-Type: text/event-stream: 指定响应内容类型为 SSE 数据流。

    • Cache-Control: no-cache: 禁止缓存,确保实时性。

    • Connection: keep-alive: 保持连接活跃。

    • 响应体为空或包含初始数据。

  3. 服务器持续推送事件: 连接建立后,服务器可以根据需要,持续地向客户端推送事件消息。每个事件消息都是一个文本块,由 data: 行开始,后面跟着事件数据,以两个换行符 \n\n 分隔。

  4. 客户端接收和处理事件: 客户端浏览器接收到 SSE 数据流后,会自动解析事件消息,并触发 message 事件 (默认事件类型) 或自定义事件类型的事件。开发者可以通过 JavaScript 监听这些事件,并处理接收到的数据。

  5. 连接保持和重连: 连接保持活跃,直到服务器或客户端主动关闭连接。如果连接中断,浏览器会自动尝试重新连接,实现自动重连机制。

Java SSE 服务端实现

import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

@RestController
public class SseController {

    private final ExecutorService executor = Executors.newSingleThreadExecutor();

    @GetMapping("/sse-spring")
    public SseEmitter sseEmitter() {
        SseEmitter emitter = new SseEmitter();

        executor.execute(() -> {
            try {
                for (int i = 0; i < 10; i++) {
                    emitter.send("Message from Spring SSE: " + i, MediaType.TEXT_PLAIN); // 发送数据
                    TimeUnit.SECONDS.sleep(1);
                }
                emitter.complete(); // 完成 SSE 连接
            } catch (IOException | InterruptedException e) {
                emitter.completeWithError(e); // 处理异常并完成连接
                Thread.currentThread().interrupt();
            }
        });

        return emitter;
    }
}

总结

服务器发送事件 (SSE) 是一种简单而高效的服务器推送技术,特别适用于 单向实时数据推送 的场景。相比轮询和长轮询,SSE 具有更高的效率和更好的实时性;相比 WebSocket,SSE 更轻量级,实现和维护更简单。


评论