使用 SSE 时不是流式输出而是等内容都输出完了一次性返回。
最近公司准备做个类似 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); // 发送错误
}
}
抓请求头 和 返回头吧
nginx 没配置吧,好像有个什么缓存的要关了
被网关缓存了,每一层网关都要检查
哈哈,上面 nginx 代理也有 sse 相关的配置的
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 的教程 www.ruanyifeng.com/blog/2017/05/server-sent_events.html
大概率 HTTP 版本低于 HTTP/1.1 。
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
GET /xx/sse/connect HTTP/1.1
Ngnix
proxy_ssl_verify off;
proxy_ssl_session_reuse off;
proxy_buffering off; # 禁用缓存谢谢大佬,我试试
大概率 nginx 的配置,网络链路上经过的中间件都排查下看看
nginx 的 proxy_buffering 配置,或者你响应头带一个 X-Accel-Buffering: no 也可以,详见 nginx.org/en/docs/http/ngx_http_proxy_module.html#proxy_buffering
proxy_http_version 1.1;
# 设置 SSE 连接的超时时间,不设置默认是 2.5 分钟
proxy_read_timeout 86400s;
# 关闭缓冲
proxy_buffering off;
# 关闭代理缓存
proxy_cache off;
sse 这一个 proxy_buffering off;就好了,其它默认
谢谢大佬,加上这个响应头就可以了。
#12 ,响应头添加 X-Accel-Buffering: no ,这个方法更好
后端返回的流式输出效果不一定是平滑的,需要前端在做一层过滤来输出,这样才能达到平滑输出的效果。
我也做了这个需求,我在后端代码加多了 3 个响应头:
Content-Type: text/event-stream
Cache-Control: no-cache
X-Accel-Buffering: no
#18 这样更好,架构复杂了,ddos waf gateway lb ,所有环节添加 proxy_buffering 很不灵活
X-Accel-Buffering: no 就行。别去瞎改 nginx 配置。
如题,此篇文章是描述C语言中的整数谜题。 假定机器字长是32位的,用2的补码表示整数。对以下C表达式,请问它们在所有情况下都正确吗?如果不是,请给出反例。 初始化: int x…
其实还是 /t/835913 的后续。发帖之后不久上海疫情,就忘了这回事…… 简述一下需求 体验不错:不需要旗舰级别,但我现在用的是一加 7pro ( 855+8G+256G …
想用线路优化机反代大内存机,都是些自己 Docker 的小工具,emby 、miniflux 、哪吒面板之类的。 都是使用的 Nginx Proxy Manager ,原网站一…
合速度