当前位置: 首页 > ai >正文

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

Hi I’m Shendi

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


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



问题

环境:SpringBoot+Nginx+AnythingLLM

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



排查

对SpringBoot接口的检查:

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

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

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

@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 对单独的几个接口关闭

location /llm/ {rewrite ^/llm/(.*)$ /api/$1 break;# 原有host 与 ipproxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header Host $host;# 支持websocketproxy_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 做路由的,保留原 Hostproxy_set_header Host $host;# 转发其他头信息proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}



END

http://www.xdnf.cn/news/4340.html

相关文章:

  • 链表——C语言
  • 常见的卷积神经网络列举
  • 用go从零构建写一个RPC(仿gRPC,tRPC)--- 版本1(Client端)
  • Umi+React+Xrender+Hsf项目开发总结
  • 基于Django汽车数据分析大屏可视化系统项目
  • SSHv2 密钥交换(Key Exchange)详解
  • 体育培训的实验室管理痛点 质检LIMS如何重构体育检测价值链
  • TikTok 矩阵运营新手实操保姆级教程 2.0 版本
  • 从一次被抄袭经历谈起:iOS App 安全保护实战
  • 【AWS+Wordpress-准备阶段】AWS注册+创建EC2实例
  • Scrapy框架之Scrapyd部署及Gerapy分布式爬虫管理框架的使用
  • 记录学习《手动学习深度学习》这本书的笔记(十)
  • 协方差与皮尔逊相关系数:从定义到应用的全面解析
  • isNotBlank和isNotEmpty有什么区别?
  • Python学习笔记--FastAPI入门常规操作
  • penEuler操作系统结合豆包测试github仓库8086-Emulator项目
  • react中的用法——setDisabled dva dispatch effects
  • leetcode 160. 相交链表
  • os梳理5——第五章:存储器管理
  • 汽车免拆诊断案例|车辆行驶中急加速车身抖动故障排除 2 例
  • C# NX二次开发:投影曲线和偏置曲线UFUN函数详解
  • Redis--哈希类型
  • 深度学习中的autograd与jacobian
  • C++ 日志系统实战第四步:设计与代码实现详解
  • 从0开始学习大模型--Day03--Agent规划与记忆
  • “胖都来”商标申请可以通过注册不!
  • 如何应对客户在验收后提出新需求?
  • ESP32蓝牙开发笔记(十四)
  • Zsh + iTerm2搭配使用教学,非常舒服,macOS
  • 系统架构-云原生架构设计