Spring Boot 整合 SSE(Server-Sent Events)全网最全


Spring Boot 整合 SSE(Server-Sent Events)

在这里插入图片描述

1、简述

SSE(Server-Sent Events)是一种基于HTTP协议的单向通信机制,允许服务器向浏览器持续发送实时更新。与WebSocket不同,SSE更简单,使用HTTP/1.1协议即可,不需要额外的协议升级。它通过简单的文本流格式(data: ...\n\n)传输事件,支持自定义事件类型和重连机制

SSE与其他技术的对比

技术协议双向通信复杂度适用场景
SSEHTTP单向服务器主动推送(如通知)
WebSocketWS双向实时聊天、游戏
长轮询HTTP半双工兼容性要求高的场景

SSE的特点:

  • 自动重连:客户端在连接断开时会自动尝试重新连接。
  • 轻量级协议:事件流格式简单,无需额外解析库。
  • 浏览器原生支持:现代浏览器通过EventSource API直接使用。

2、Spring Boot 中的SSE实现

2.1 添加依赖与配置

验证Spring Boot版本兼容性:确保使用Spring Boot 2.2+版本以获得更好的异步支持。

<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>3.1.0</version>
</parent>

2.2 实现后端接口

代码深度解析

  • 使用Stream.generate生成数据流,但需注意无限流会导致线程阻塞,推荐结合异步线程池。
  • 添加事件ID和重试机制(增强SSE规范支持):
@GetMapping(value = "/sse/stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public Flux<String> stream() {
    return Flux.interval(Duration.ofSeconds(1))
              .map(sequence -> "id: " + sequence + "\n" 
                             + "data: " + LocalTime.now() + "\n\n")
              .take(10);
}

2.3 超时与异常处理

精细化配置

  • 通过SseEmitter设置超时回调,记录未完成的连接:
emitter.onTimeout(() -> {
    log.warn("SSE连接超时:{}", emitter);
    emitters.remove(emitter);
});
  • 全局异常处理:使用@ExceptionHandler捕获IOException,避免连接中断导致服务不可用。

2.4 前端实现优化

增强健壮性

  • 监听特定事件类型并处理重连:
eventSource.addEventListener("customEvent", function(e) {
    console.log("自定义事件数据:", e.data);
});

eventSource.onerror = function() {
    setTimeout(() => new EventSource('/sse/stream'), 5000); // 5秒后重连
};
  • 添加心跳检测:服务器定期发送注释行(:keep-alive\n)防止代理超时。

3、高级实践

3.1 结合Spring Security实现鉴权

保护SSE端点

@GetMapping("/sse/private-stream")
public SseEmitter privateStream(Authentication authentication) {
    if (authentication == null) {
        throw new SecurityException("未授权访问");
    }
    return ssePushService.subscribe();
}

Token验证:前端在初始化EventSource时携带Token:

new EventSource('/sse/private-stream?token=xxxx');

3.2 分布式场景下的解决方案

使用消息队列广播事件(以Redis Pub/Sub为例):

  1. 引入依赖:
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
  1. 订阅Redis频道并推送消息:
@Bean
public MessageListenerAdapter redisListener(SsePushService pushService) {
    return new MessageListenerAdapter((message, channel) -> 
        pushService.pushMessage(message.toString()));
}

3.3 性能监控与调优

  • 监控连接数:通过/actuator/metrics/sse.emitters端点(需集成Actuator)。
  • 背压控制:使用Project Reactor的Flux处理背压,避免服务器过载。

4、注意事项(增强版)

  • 浏览器兼容性

    • IE完全不支持,可通过polyfill(如eventsource库)降级为长轮询。
    • 移动端浏览器需测试网络切换(如4G/WiFi)对连接的影响。
  • 消息格式规范

    • 每条消息以data:开头,结尾必须有两个换行符。
    • 发送JSON数据需转义换行符:data: {\"time\": \"12:00\"}\n\n
  • 安全加固

    • 启用HTTPS防止中间人攻击。
    • 限制每IP连接数,防止DDoS攻击。

5、实战案例:实时日志监控系统

架构设计

  1. 日志收集:Filebeat监听日志文件变动。
  2. 消息中转:Kafka接收日志并缓存。
  3. SSE推送:Spring Boot消费Kafka消息并广播。

关键代码

@KafkaListener(topics = "logs")
public void handleLog(String logMessage) {
    ssePushService.pushMessage(logMessage);
}

6、调试与测试技巧

  • 使用Curl测试SSE
    curl -N http://localhost:8080/sse/stream
    
  • 浏览器开发者工具
    • 网络面板查看EventStream分帧详情。
    • 控制台调试EventSource事件监听。

延伸阅读

### 使用 Server-Sent Events (SSE) 实现流式传输 #### SSE 基本概念 Server-Sent Events (SSE) 是一种允许服务器向浏览器推送更新的技术。与 WebSocket 不同的是,SSE 只支持单向通信——即仅由服务器发送给客户端的数据流动[^1]。 #### 客户端实现 在 HTML 页面中可以通过 `EventSource` 对象来创建到服务器的连接并监听事件: ```javascript if(typeof(EventSource)!=="undefined") { var source=new EventSource("/stream"); source.onmessage=function(event){ document.getElementById("result").innerHTML+=event.data + "<br>"; }; } else { console.log("您的浏览器不支持 Server-sent events..."); } ``` 上述代码片段展示了如何建立一个简单的 SSE 连接,并将收到的消息显示在一个指定 ID 的 DOM 元素里。 #### 服务端实现 对于 Python 开发者来说,在 Flask 或 Django 中设置 SSE 非常简便。下面是一个基于 Flask 的例子: ```python from flask import Flask, Response import time app = Flask(__name__) @app.route('/stream') def stream(): def generate(): while True: yield f"data: {time.strftime('%Y-%m-%d %H:%M:%S')}\n\n" time.sleep(1) return Response(generate(), mimetype='text/event-stream') if __name__ == "__main__": app.run(debug=True) ``` 这段脚本会每秒向已订阅此路径 `/stream` 的所有客户端广播当前时间戳[^2]。 #### 应用实例:文件下载进度条 当涉及到大型文件下载时,利用 SSE 技术可以让用户体验更加友好。比如可以在 Spring Boot 后台配合前端框架如 Vue.js 来构建这样的应用案例。每当有新的下载状态变化发生时就触发一次 HTTP 请求返回最新的百分比数值给用户界面展示出来[^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值