rainfy
V2EX  ›  Java

使用 SSE 时不是流式输出而是等内容都输出完了一次性返回。

  •  
  •   rainfy · Feb 26, 2025 · 7416 views
    This topic created in 619 days ago, the information mentioned may be changed or developed.
    最近公司准备做个类似 GPT 一样的聊天功能,使用 SSE 来实现。 写了个 demo ,我在本机测试没问题,上了测试环境发现输出的内容都是等待后一次性输出到前端,并不是打字机的效果。
    服务端代码如下:
    @GetMapping(value = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitter c() {
    SseEmitter sseEmitter = new SseEmitter();

    log.error("xxx start");
    //调用流式会话服务
    new Thread(() -> streamChatCompletion(sseEmitter)).start();
    log.error("xxx end");
    //及时返回 SseEmitter 对象
    return sseEmitter;
    }

    public void streamChatCompletion(SseEmitter emitter) {
    try {
    for (int i = 0; i < 3; i++) {
    String o = "test" + i;
    emitter.send(o);
    Thread.sleep(1000); // 每秒发送一次
    }
    emitter.send(SseEmitter.event().name(" stop").data(""));
    emitter.complete(); // 完成发送
    } catch (IOException | InterruptedException e) {
    emitter.completeWithError(e); // 发送错误
    }
    }
    21 replies  •  2025-02-27 13:01:55 +08:00
    guanhui07
    guanhui07
    Feb 26, 2025
    1
    抓请求头 和 返回头吧
    xxkuboy
    xxkuboy
    Feb 26, 2025
    2
    nginx 没配置吧,好像有个什么缓存的要关了
    ex1gtnim7d
    ex1gtnim7d
    Feb 26, 2025
    3
    被网关缓存了,每一层网关都要检查
    xuelang
    xuelang
    Feb 26, 2025
    4
    哈哈,上面 nginx 代理也有 sse 相关的配置的
    magicZ
    magicZ
    Feb 26, 2025
    5
    public void demo( HttpServletResponse httpServletResponse) throws IOException {
    httpServletResponse.setContentType("text/event-stream");
    httpServletResponse.setCharacterEncoding("UTF-8");
    httpServletResponse.setHeader("Cache-Control", "no-cache");
    ServletOutputStream outputStream = httpServletResponse.getOutputStream();
    while{
    outputStream.write(("data: " + 字符串 + "\n\n").getBytes());
    }
    outputStream.write(("data: done\n\n").getBytes());
    outputStream.flush();
    } 查查 sse 的教程 https://www.ruanyifeng.com/blog/2017/05/server-sent_events.html
    lavvrence
    lavvrence
    Feb 26, 2025
    6
    大概率 HTTP 版本低于 HTTP/1.1 。
    rainfy
    rainfy
    OP
    Feb 26, 2025
    7
    @guanhui07
    Response Headers:
    HTTP/1.1 200 OK
    Transfer-Encoding: chunked
    Access-Control-Allow-Credentials: true
    Access-Control-Allow-Origin: null
    Access-Control-Expose-Headers: permission, username, eagleeye-traceid
    Connection: keep-alive
    Content-Type: text/event-stream;charset=UTF-8
    Date: Wed, 26 Feb 2025 02:00:08 GMT
    Keep-Alive: timeout=4
    Proxy-Connection: keep-alive
    Server: f6car
    Set-Cookie: romaSESSIONID=de1f56ef-5301-412a-8537-abe613dd1dc1; Path=/roma; HttpOnly
    Vary: Origin
    X-Application-Context: xx:test:8888

    Request Headers:
    GET /xx/sse/connect HTTP/1.1
    Accept: text/event-stream
    Accept-Encoding: gzip, deflate
    Accept-Language: zh-CN,zh;q=0.9
    Cache-Control: no-cache
    DNT: 1
    Host: report-pre.f6car.com
    Origin: null
    Proxy-Connection: keep-alive
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/133.0.0.0 Safari/537.36
    rainfy
    rainfy
    OP
    Feb 26, 2025
    8
    @jaylee4869 GET /xx/sse/connect HTTP/1.1
    CHTuring
    CHTuring
    Feb 26, 2025
    9
    Ngnix

    ```
    proxy_ssl_verify off;
    proxy_ssl_session_reuse off;
    proxy_buffering off; # 禁用缓存
    ```
    rainfy
    rainfy
    OP
    Feb 26, 2025
    10
    @CHTuring 谢谢大佬,我试试
    yevXxHmg
    yevXxHmg
    Feb 26, 2025
    11
    大概率 nginx 的配置,网络链路上经过的中间件都排查下看看
    KingFong
    KingFong
    Feb 26, 2025❤️2
    12
    nginx 的 proxy_buffering 配置,或者你响应头带一个 X-Accel-Buffering: no 也可以,详见 https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering
    weenhall5
    weenhall5
    Feb 26, 2025
    13
    proxy_http_version 1.1;
    # 设置 SSE 连接的超时时间,不设置默认是 2.5 分钟
    proxy_read_timeout 86400s;
    # 关闭缓冲
    proxy_buffering off;
    # 关闭代理缓存
    proxy_cache off;
    salmon5
    salmon5
    Feb 26, 2025
    14
    sse 这一个 proxy_buffering off;就好了,其它默认
    rainfy
    rainfy
    OP
    Feb 26, 2025
    15
    @yanjieee 谢谢大佬,加上这个响应头就可以了。
    salmon5
    salmon5
    Feb 26, 2025
    16
    @yanjieee #12 ,响应头添加 X-Accel-Buffering: no ,这个方法更好
    foolyf
    foolyf
    Feb 26, 2025
    17
    后端返回的流式输出效果不一定是平滑的,需要前端在做一层过滤来输出,这样才能达到平滑输出的效果。
    SoulFlame
    SoulFlame
    Feb 26, 2025❤️1
    18
    我也做了这个需求,我在后端代码加多了 3 个响应头:
    Content-Type: text/event-stream
    Cache-Control: no-cache
    X-Accel-Buffering: no
    salmon5
    salmon5
    Feb 26, 2025
    19
    @SoulFlame #18 这样更好,架构复杂了,ddos waf gateway lb ,所有环节添加 proxy_buffering 很不灵活
    tf2
    tf2
    Feb 26, 2025❤️1
    20
    X-Accel-Buffering: no 就行。别去瞎改 nginx 配置。
    japeth
    japeth
    Feb 27, 2025
    21
    我这边使用的 go 语言,gin 封装的脚手架,要把 gzip 要关掉 。
    About   ·   Help   ·   Advertise   ·   Blog   ·   API   ·   FAQ   ·   Privacy   ·   Solana   ·   1657 Online   Highest 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 48ms · UTC 11:37 · PVG 19:37 · LAX 03:37 · JFK 06:37
    ♥ Do have faith in what you're doing.