使用 SSE 时不是流式输出而是等内容都输出完了一次性返回。 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
rainfy
V2EX    Java

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

  •  
  •   rainfy 226 天前 3461 次点击
    这是一个创建于 226 天前的主题,其中的信息可能已经有所发展或是发生改变。
    最近公司准备做个类似 GPT 一样的聊天功能,使用 SSE 来实现。 写了个 demo ,我在本机测试没问题,上了测试环境发现输出的内容都是等待后一次性输出到前端,并不是打字机的效果。
    服务端代码如下:
    @GetMapping(value = "/sse", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
    public SseEmitterc() {
    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 条回复    2025-02-27 13:01:55 +08:00
    guanhui07
        1
    guanhui07  
       226 天前
    抓请求头 和 返回头吧
    xxkuboy
        2
    xxkuboy  
       226 天前
    nginx 没配置吧,好像有个什么缓存的要关了
    ex1gtnim7d
        3
    ex1gtnim7d  
       226 天前
    被网关缓存了,每一层网关都要检查
    xuelang
        4
    xuelang  
       226 天前
    哈哈,上面 nginx 代理也有 sse 相关的配置的
    magicZ
        5
    magicZ  
       226 天前
    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
        6
    lavvrence  
       226 天前
    大概率 HTTP 版本低于 HTTP/1.1 。
    rainfy
        7
    rainfy  
    OP
       226 天前
    @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=
    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
        8
    rainfy  
    OP
       226 天前
    @jaylee4869 GET /xx/sse/connect HTTP/1.1
    CHTuring
        9
    CHTuring  
       226 天前
    Ngnix

    ```
    proxy_ssl_verify off;
    proxy_ssl_session_reuse off;
    proxy_buffering off; # 禁用缓存
    ```
    rainfy
        10
    rainfy  
    OP
       226 天前
    @CHTuring 谢谢大佬,我试试
    yevXxHmg
        11
    yevXxHmg  
       226 天前
    大概率 nginx 的配置,网络链路上经过的中间件都排查下看看
    KingFong
        12
    KingFong  
    PRO
       226 天前   2
    nginx 的 proxy_buffering 配置,或者你响应头带一个 X-Accel-Buffering: no 也可以,详见 https://nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering
    weenhall5
        13
    weenhall5  
       226 天前
    proxy_http_version 1.1;
    # 设置 SSE 连接的超时时间,不设置默认是 2.5 分钟
    proxy_read_timeout 86400s;
    # 关闭缓冲
    proxy_buffering off;
    # 关闭代理缓存
    proxy_cache off;
    salmon5
        14
    salmon5  
       226 天前
    sse 这一个 proxy_buffering off;就好了,其它默认
    rainfy
        15
    rainfy  
    OP
       226 天前
    @yanjieee 谢谢大佬,加上这个响应头就可以了。
    salmon5
        16
    salmon5  
       226 天前
    @yanjieee #12 ,响应头添加 X-Accel-Buffering: no ,这个方法更好
    foolyf
        17
    foolyf  
       226 天前
    后端返回的流式输出效果不一定是平滑的,需要前端在做一层过滤来输出,这样才能达到平滑输出的效果。
    SoulFlame
        18
    SoulFlame  
       226 天前   1
    我也做了这个需求,我在后端代码加多了 3 个响应头:
    Content-Type: text/event-stream
    Cache-Control: no-cache
    X-Accel-Buffering: no
    salmon5
        19
    salmon5  
       226 天前
    @SoulFlame #18 这样更好,架构复杂了,ddos waf gateway lb ,所有环节添加 proxy_buffering 很不灵活
    lambdaq
        20
    lambdaq  
          1
    X-Accel-Buffering: no 就行。别去瞎改 nginx 配置。
    japeth
        21
    japeth  
       225 天前
    我这边使用的 go 语言,gin 封装的脚手架,要把 gzip 要关掉 。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     5283 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 33ms UTC 08:18 PVG 16:18 LAX 01:18 JFK 04:18
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86