SSE介绍

目录

SSE概念

SSE的特点

应用场景

优点

缺点

轮询(Polling)概念

轮询特点

应用场景

优点

缺点

Websocket概念

特点

应用场景

优点

缺点

SSE、轮询、websocket对比

SSE实现

pom依赖

SSE控制器

postman模拟客户端发起请求

总结


SSE概念

SSE(Server-Sent Events)是一种服务器向客户端推送实时数据的技术。

SSE的特点

  • 单向通信:服务器向客户端推送数据,客户端不能通过 SSE 向服务器发送数据
  • 基于 HTTP:使用标准的 HTTP 协议,长连接方式
  • 自动重连:客户端在连接断开时会自动重连
  • 轻量级:实现简单,适合服务器向客户端推送实时数据的场景

应用场景

  • 实时通知:如新闻更新、股票价格变动、天气预报等。

  • 日志推送:服务器向客户端实时推送日志信息。

  • 进度更新:如文件上传/下载进度、任务处理进度等。

优点

  • 实现简单,兼容性好(基于 HTTP)。

  • 支持自动重连,适合长时间运行的场景。

缺点

  • 单向通信,客户端无法通过 SSE 向服务器发送数据。

  • 不支持二进制数据,只支持文本数据。

轮询(Polling)概念

轮询特点

  • 客户端主动请求:客户端定期向服务器发送请求,检查是否有新的数据
  • 高延迟:数据更新的实时性取决于客户端的轮询间隔
  • 资源消耗:频繁的请求会增加客户端和服务器的资源消耗

应用场景

简单,对实时性要求不高的场景,如简单的状态检查、数据更新等

优点

  • 实现简单,兼容性好
  • 适合对实时性要求不高的应用场景

缺点

  • 高延迟,实时性差
  • 频繁请求,浪费资源

Websocket概念

特点

双向通信:客户端和服务器可以实时双向通信

基于TCP:使用独立的websocket协议,性能高

低延迟:适合实时性要求很高的场景

应用场景

实时聊天:如在线客服、聊天室等

实时协作:如在线文档编辑、多人游戏等

高频数据交互:如股票交易、数据监控等

优点

  • 低延迟,实时性高
  • 支持双向通信

缺点

  • 实现复杂,需要额外的websocket协议支持
  • 对服务器资源消耗较大

SSE、轮询、websocket对比

|-----------|------------|-----------|-----|-------|------------------|
| 技术 | 通信方式 | 协议 | 实时性 | 实现复杂度 | 适用场景 |
| SSE | 单向,服务器→客户端 | HTTP | 高 | 简单 | 实时通知、进度更新、日志推送等 |
| 轮询 | 单向,客户端→服务器 | HTTP | 低 | 简单 | 简单数据更新、状态检查 |
| websocket | 双向通信 | websocket | 极高 | 复杂 | 实时聊天、在线协作、高频数据交互 |

SSE实现

在springboot项目中,实现一个简单的SSE程序,步骤如下

pom依赖

复制代码
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>

SSE控制器

java 复制代码
package com.tml.mouseDemo.controller;

import cn.hutool.core.date.DateUtil;
import com.alibaba.ttl.threadpool.TtlExecutors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.servlet.mvc.method.annotation.SseEmitter;

import java.io.IOException;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

@RestController
@Slf4j
public class SSEController {

    // 存储所有连接的客户端(线程安全)
    private final CopyOnWriteArrayList<SseEmitter> emitters = new CopyOnWriteArrayList<>();

    // 定时任务线程池
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    //使用ttl装饰线程池,是为了方便使用threadLocal
    ScheduledExecutorService ttlScheduledExecutorService = TtlExecutors.getTtlScheduledExecutorService(scheduler);

    /**
     * 客户端连接 SSE 的入口
     * sse的content-type是text/event-stream
     */
    @GetMapping(path = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter handleSSE(@RequestParam String userId) {


        SseEmitter emitter = new SseEmitter(60_000L); // 超时时间 60 秒

        // 将新的 emitter 加入集合
        emitters.add(emitter);
        log.info("SSE emitter started");

        // 注册完成和超时的回调(清理资源)
        emitter.onCompletion(() -> {
            log.info("SSE emitter stopped");
            emitters.remove(emitter);
        });
        emitter.onTimeout(() -> {
            log.info("SSE emitter timeout");
            emitters.remove(emitter);
        });

        // 启动定时任务,向客户端推送数据
        ttlScheduledExecutorService.scheduleAtFixedRate(() -> {
            try {
                String message = "Hello " + userId + "! Time: " + DateUtil.now();
                log.info("SSE emitter sending message: {}", message);
                emitter.send(message);
            } catch (IOException e) {
                emitter.completeWithError(e);
            }
        }, 0, 5, TimeUnit.SECONDS); // 每5秒发送一次

        return emitter;
    }
}

启动服务端后,再启动客户端

postman模拟客户端发起请求

总结

在AI时代,很多大模型的开放平台的api均支持流式返回和非流式返回,这里的流式返回,就是使用的SSE,比如kimi的开放平台

在实际应用中,可能还有其他场景适用服务器单向客户端推送数据,这个时候SSE就派上用场了,欢迎评论区留言,说出你们实际业务中,有哪些场景使用了SSE!

相关推荐
DeepSeek-大模型系统教程39 分钟前
推荐 7 个本周 yyds 的 GitHub 项目。
人工智能·ai·语言模型·大模型·github·ai大模型·大模型学习
小雷FansUnion3 小时前
深入理解MCP架构:智能服务编排、上下文管理与动态路由实战
人工智能·架构·大模型·mcp
Fireworkitte3 小时前
Apache POI 详解 - Java 操作 Excel/Word/PPT
java·apache·excel
weixin-a153003083163 小时前
【playwright篇】教程(十七)[html元素知识]
java·前端·html
DCTANT3 小时前
【原创】国产化适配-全量迁移MySQL数据到OpenGauss数据库
java·数据库·spring boot·mysql·opengauss
Touper.3 小时前
SpringBoot -- 自动配置原理
java·spring boot·后端
黄雪超3 小时前
JVM——函数式语法糖:如何使用Function、Stream来编写函数式程序?
java·开发语言·jvm
ThetaarSofVenice4 小时前
对象的finalization机制Test
java·开发语言·jvm
望获linux5 小时前
【实时Linux实战系列】CPU 隔离与屏蔽技术
java·linux·运维·服务器·操作系统·开源软件·嵌入式软件
JosieBook5 小时前
【Java编程动手学】使用IDEA创建第一个HelloJava程序
java·开发语言·intellij-idea