springboot+sse的实现案例

一 sse

1.1 介绍

SSE(Server-Sent Events,服务器发送事件)是一种基于 HTTP 的服务器向客户端单向推送实时数据 的技术,属于 HTML5 标准的一部分。它允许服务器主动向客户端发送数据流,适用于低延迟、单向实时更新的场景(如新闻推送、实时监控、日志流展示等)。

1和websocket对比

2.输出的数据格式:

1.2 遇到的问题案例

1.报错代码

SseEmitter emitter = new SseEmitter(300_000L*20)

emitter.send(SseEmitter.event().data(message));

2.nginx这样配置

location /bocai-chat {

proxy_send_timeout 3600s;

proxy_connect_timeout 1200s;

proxy_read_timeout 3600s;

proxy_buffering off;

proxy_pass http://bocaicluster/bocai-chat;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

}

3.这段代码提示报

org.springframework.web.context.request.async.AsyncRequestNotUsableException: ServletOutputStream failed to flush: java.io.IOException: Connection reset by peer

4.前端页面通过nginx代理访问且并没有刷新关闭页面,通过nginx代理后的页面访问报这个错误,直接绕过nginx返回后端服务程序是正常。最后排查的是nginx代理的后端负载服务器存在问题。

二 sse的案例

2.1 两种情况的说明

2.2 同步阻塞-发送数据

说明:同步阻塞:能发送数据,但无法触发onCompletion回调的执行。

因为同步阻塞,发送send,complete方法后,emitter.onCompletion()还没有注册。无法触发。

同时如果浏览器关闭,send发送也不会触发异常。

1.代码

复制代码
 /**
     * @author admin
     * @description      同步阻塞
     * @date 2025/12/20 12:39
     * @param []
     * @return org.springframework.web.servlet.mvc.method.annotation.SseEmitter
     */
    @GetMapping("/stream3")
    public SseEmitter streamDataCallBack() {
        SseEmitter emitter = new SseEmitter(300000L); // 0表示不超时
        // 设置完成和超时回调
        emitter.onCompletion(() -> System.out.println("完成.."));
        emitter.onTimeout(() -> {
                    System.out.println("超时...");
                    emitter.complete(); // 超时后主动完成
                }
        );
        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
            // 发送初始连接成功消息
            try {
                emitter.send(SseEmitter.event()
                        .name("CONNECTED")
                        .data("{\"status\": \"connected\", \"timestamp\": \"" +
                                System.currentTimeMillis() + "\"}"));
//              .data("你好当前是:"+System.currentTimeMillis()));
            } catch (Exception e) {
                System.out.println("报异常了:"+e);
                emitter.completeWithError(e);
            }
        try {
            Thread.sleep(30000);
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }
        System.out.println("正常....");
            emitter.complete(); // 此时回调已注册,会触发 onCompletion
        return emitter;
    }

2.效果图

控制台:

2.3 异步非阻塞-发送数据

1.能够触发,oncompletion的方法。加了异步处理

复制代码
 /**
    * @author admin
    * @description       正常场景
    * @date 2025/12/20 12:39
    * @param []
    * @return org.springframework.web.servlet.mvc.method.annotation.SseEmitter
    */
    @GetMapping("/stream")
    public SseEmitter streamData() {
        SseEmitter emitter = new SseEmitter(0L); // 0表示不超时

        // 将新的emitter添加到集合中
       // emitters.add(emitter);

        // 设置完成和超时回调
        emitter.onCompletion(() -> System.out.println("完成.."));
        emitter.onTimeout(() -> {
                    System.out.println("超时...");
                    emitter.complete(); // 超时后主动完成
                }
        );
        executor.schedule(() -> {
        // 发送初始连接成功消息
        try {
            emitter.send(SseEmitter.event()
                    .name("CONNECTED")
                    .data("{\"status\": \"connected\", \"timestamp\": \"" +
                            System.currentTimeMillis() + "\"}"));
//              .data("你好当前是:"+System.currentTimeMillis()));
        } catch (IOException e) {
            System.out.println("报异常了:"+e);
            emitter.completeWithError(e);
        }
            System.out.println("正常....");
            emitter.complete(); // 此时回调已注册,会触发 onCompletion
        }, 50, TimeUnit.SECONDS);
//       emitter.complete();
        return emitter;
    }

2.效果

2.4 异步非阻塞-正常发送数据-关闭浏览器

1.在浏览器输入地址访问:大概10s后,关闭浏览器

2.后端设置了延迟50s,在50s后开始执行,发现客户端已经断开,报错

2.5 异步非阻塞-超时

1.设置超时小一点,业务执行长一点;200毫秒肯定小于1秒

2.执行效果

控制台:看到触发超时回调方法

相关推荐
12344522 分钟前
Agent入门实战-一个题目生成Agent
人工智能·后端
IT_陈寒4 分钟前
Java性能调优实战:5个被低估却提升30%效率的JVM参数
前端·人工智能·后端
快手技术5 分钟前
AAAI 2026|全面发力!快手斩获 3 篇 Oral,12 篇论文入选!
前端·后端·算法
颜酱7 分钟前
前端算法必备:滑动窗口从入门到很熟练(最长/最短/计数三大类型)
前端·后端·算法
8***f3958 分钟前
Spring容器初始化扩展点:ApplicationContextInitializer
java·后端·spring
用户2986985301410 分钟前
C#: 如何自动化创建Word可填写表单,告别手动填写时代
后端·c#·.net
r_oo_ki_e_14 分钟前
java22--常用类
java·开发语言
linweidong25 分钟前
C++ 中避免悬挂引用的企业策略有哪些?
java·jvm·c++
用户937611475816126 分钟前
并发编程三大特性
java·后端
阿在在28 分钟前
Spring 系列(二):加载 BeanDefinition 的几种方式
java·后端·spring