记一次SSE数据被缓存导致实时性失效问题

Hi I'm Shendi

最近在编写SSE接口遇到了缓存问题,导致实时性失效,在这里记录一下。


记一次SSE数据被缓存导致实时性失效问题


问题

环境:SpringBoot+Nginx+AnythingLLM

SSE接口调用拥有缓存,导致数据被缓存后才返回给前端。

排查

对SpringBoot接口的检查:

检查接口代码,直接使用 resp.OutputStream 或者使用 SseEmitter 皆有此问题

检查接口中对AnythingLLM调用的代码,发现使用BufferedReader.readLine,将其直接改为InputStream.read判断\n,效果的确好了一点,但依然有此问题。

编写测试代码,看是否是接口问题:

java 复制代码
@Anonymous
@GetMapping(value = "/test", produces = MediaType.TEXT_EVENT_STREAM_VALUE)
public void test(HttpServletResponse resp) throws Exception {
    resp.setContentType("text/event-stream;charset=UTF-8");
    resp.setCharacterEncoding("UTF-8");
    // 禁止压缩,防止流式被缓存
    resp.setHeader("Content-Encoding", "identity");
    resp.setHeader("Cache-Control", "no-cache");

    OutputStream output = resp.getOutputStream();

    for (int i = 0; i < 20; i++) {
        output.write(("data: " + RespCode.toResp(RespCode.PARAM_NULL) + "\n\n").getBytes());
        output.flush();
        Thread.sleep(2000);
    }
}

测试发现无问题,前端稳定的两秒收到数据(皆使用Nginx反向代理)

对 AnythingLLM的检查:

直接调用接口,发现问题复现,然后猜测是否Nginx的问题,不使用代理访问,一切正常。

解决

最终的问题就是Nginx的问题,Nginx默认会将数据进行缓存,要进行相应配置,并且SSE接口就那么几个,所以可以使用rewrite 对单独的几个接口关闭

sh 复制代码
location /llm/ {
    rewrite ^/llm/(.*)$ /api/$1 break;
    # 原有host 与 ip
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Host $host;
    # 支持websocket
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";

    proxy_pass   http://127.0.0.1:3001;
}
location ~ ^/llm/v1/workspace/[^/]+/thread/[^/]+/stream-chat$ {
    rewrite ^/llm/(.*)$ /api/$1 break;

    proxy_pass   http://127.0.0.1:3001;

    # 关闭缓冲,确保实时转发
    proxy_buffering off;
    proxy_cache off;

    # 设置 HTTP/1.1 以保持长连接
    proxy_http_version 1.1;
    proxy_set_header Connection '';

    # 防止 gzip 压缩,避免 chunked 被打包
    gzip off;

    # 增加超时时间,避免 SSE 长连接被断开
    proxy_read_timeout 3600s;
    proxy_send_timeout 3600s;

    # 如果后端是基于 Host 做路由的,保留原 Host
    proxy_set_header Host $host;

    # 转发其他头信息
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}

END

相关推荐
真上帝的左手6 小时前
30. 技术专题-‌应用框架组件-缓存-Redis
数据库·redis·分布式·缓存·中间件
bksczm7 小时前
C++Redis开发(Ubuntu 22.04)
数据库·redis·缓存
goehou7 小时前
缓存该删还是该改,LLM 服务里的双写问题
redis·缓存·llm·一致性·系统设计
利威尔xu19 小时前
Go IM 源码实战(14):本地缓存快 3000 倍,失效却难 10 倍
后端·缓存·微服务·面试·golang
程序猿编码1 天前
解决 LLM 算力浪费,一套统一 KV 管理层实现缓存复用
人工智能·神经网络·机器学习·缓存·llm·大模型推理
zrc0070071 天前
steam无法登录 steam错误 登录时出现错误。请稍后再试。解决办法 steam无法登录解决办法 湖南地区steam DNS问题解决办法
windows·经验分享·游戏·缓存·游戏程序·创业创新·玩游戏
CCblandy1 天前
缓存淘汰实测:一次全表扫描把 LRU 命中率从 46% 打到 38%,W-TinyLFU 守住 50% 却贵 11 倍
后端·python·缓存·性能优化·架构
Wang's Blog1 天前
Java 项目实战: 交友项目 - 小视频模块实战:访客记录、FastDFS 存储与 SpringCache 缓存
java·缓存·交友
麻瓜code1 天前
双写一致性:为什么是“删缓存“,而不是“改缓存“
java·缓存·mybatis
snow@li1 天前
redis:RedisDesktopManager(RDM/RESP.app)Redis 数据可视化全景深度梳理
数据库·redis·缓存