使用 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 配置。
如题,比如使用本地 flux1 模型 生成一张需要等待 30 秒的图片 1.直接 controller 内同步返回,相信 web 框架的并发能力 2.使用 redis 队列 并…
背景介绍 国内普本毕业"1.5 年", 专业"数据科学与大数据", 大学四年天天逃课, gpa 稀烂 实习经历 两段实习都是做数据分析相关的, 简单的说就是数据的 etl 找工…
做个镜像真的折磨 环境不都是开发自己做的吗,找不到包和基础设施有什么关系, 难道你是算法? 我们算法不用我做的 docker image 也是和你一样报怨,甚至要写个 ex…
合速度