浅谈Spring Cloud Gateway 转发 SSE 的那些坑

 更新时间:2026年06月02日 09:31:53   作者:go 码头整点薯条  
本文主要介绍了SSE在Gateway场景下的常见问题题并提供了解决方案,包括禁止响应缓存、正确配置超时设置、透传Header等确保Gateway不加工SSE流式响应,帮助开发者避免常见错误

—— 为什么你本地能流,一上网关就“卡死”

一、背景:SSE 本地好好的,上了 Gateway 全废了

在做 AI 问答流式输出时,我最初的架构是这样的:

Browser
  ↓
Spring Cloud Gateway
  ↓
AI Service(SSE)

现象非常诡异:

  • 直连 AI 服务:✅ 一边生成一边返回
  • 走 Gateway:❌ 页面一直 loading
  • 最后一次性返回,或者直接超时

当时的第一反应是:

“是不是 SSE 不能过网关?”

结论是:

SSE 可以过 Gateway,但默认配置下,几乎一定会翻车

二、SSE 在 Gateway 场景下到底“特殊”在哪?

1️⃣ SSE 的几个关键特性

  • 长连接
  • 响应体是持续写入
  • 没有 Content-Length
  • 依赖 Transfer-Encoding: chunked

而 Gateway 的本质是:

一个“智能代理” + 各种 Filter

这就产生了天然冲突。

三、第一个坑:响应被 Gateway “缓存”了

❌ 错误表现

  • AI 服务已经在流式返回
  • Gateway 一直等
  • 最后一次性吐给客户端

❌ 根本原因

Gateway 默认会尝试:

  • 聚合 response body
  • 处理后再返回
  • 破坏了 SSE 的“边写边发”

✅ 正确做法:禁止响应缓存

spring:
  cloud:
    gateway:
      httpclient:
        response-timeout: 0s

并且不要使用这些 Filter:

  • ModifyResponseBody
  • RewriteResponseBody
  • CacheRequestBody

👉 这些 Filter 天生会吃掉流

四、第二个坑:超时设置会“悄悄杀死连接”

❌ 常见错误配置

spring:
  cloud:
    gateway:
      httpclient:
        connect-timeout: 5000
        response-timeout: 30s

对普通接口没问题
对 SSE 来说是 致命的

原因

  • SSE 是“永不结束的响应”
  • Gateway 会认为:

“30 秒还没结束?那我关了”

✅ SSE 专用超时配置

spring:
  cloud:
    gateway:
      httpclient:
        connect-timeout: 5000
        response-timeout: 0s   # 关键

五、第三个坑:Header 被 Gateway “改坏了”

❌ 错误现象

  • 前端 EventSource 连不上
  • 或连接成功但不触发 onmessage

常见罪魁祸首

❌ Content-Type 被改写

Content-Type: application/json 

而不是:

text/event-stream 

✅ Gateway 必须“原样透传”

spring:
  cloud:
    gateway:
      default-filters:
        - PreserveHostHeader

并且不要在 Filter 里手动 set header。

六、第四个坑:HTTP/1.1 被无意中升级成 HTTP/2

问题表现

  • 某些客户端收不到流
  • 特别是 EventSource

原因

  • HTTP/2 对流量有额外 buffering
  • 某些浏览器 / 代理对 SSE + H2 支持不好

✅ 强制 Gateway 使用 HTTP/1.1

spring:
  cloud:
    gateway:
      httpclient:
        protocol: HTTP11

七、一个「能跑通 SSE 的 Gateway 路由示例」

spring:
  cloud:
    gateway:
      routes:
        - id: ai-sse
          uri: lb://mb-ai
          predicates:
            - Path=/ai/health_manager/stream
          filters:
            - StripPrefix=1

关键点总结:

  • 不改 response body
  • 不缓存
  • 不超时
  • 不动 header

八、前端为什么“必须立即有输出”?

很多人忽略了这一点。

SSE 的一个隐形规则

如果服务端迟迟不发送第一条 data,浏览器会以为连接失败

建议做法

AI 服务端:

emitter.send(" "); // 先发一个空事件 

Gateway 才会立刻把连接“刷”给客户端。

九、排查 SSE 在 Gateway 卡死的 checklist

当你遇到“能连但不流”的情况,按顺序查:

  • Gateway response-timeout 是否为 0
  • 是否使用了 ModifyResponseBody
  • Content-Type 是否是 text/event-stream
  • 是否被 HTTP/2 代理
  • AI 是否第一时间发送 data
  • 是否被 nginx 二次代理缓冲

十、我的最终经验总结

SSE 在 Gateway 下不是“配置问题”,而是“思维问题”

你必须接受:

  • SSE 不是一个“普通 HTTP 响应”
  • Gateway 不应该“加工它”
  • 它只应该当一根“水管”

一旦你试图:

  • 解析
  • 缓存
  • 重写

👉 流式必死。

十一、什么时候我会“绕开 Gateway”?

说一句大实话:

  • 超高频 AI 流
  • 大并发长连接
  • 对延迟极敏感

👉 我会让前端直连 AI 服务

Gateway 只做:

  • 鉴权
  • 路由发现

十二、写在最后

如果你在做:

  • AI 对话
  • ChatGPT 类应用
  • 实时推送

那你迟早会和 SSE + Gateway 正面交锋。

到此这篇关于浅谈Spring Cloud Gateway 转发 SSE 的那些坑的文章就介绍到这了,更多相关Spring Cloud Gateway 转发 SSE内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring security密码加密实现代码实例

    Spring security密码加密实现代码实例

    这篇文章主要介绍了Spring security密码加密实现代码实例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2020-04-04
  • SpringBoot如何使用RateLimiter通过AOP方式进行限流

    SpringBoot如何使用RateLimiter通过AOP方式进行限流

    这篇文章主要介绍了SpringBoot如何使用RateLimiter通过AOP方式进行限流,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教
    2022-06-06
  • SpringMvc MultipartFile实现图片文件上传示例

    SpringMvc MultipartFile实现图片文件上传示例

    本篇文章主要介绍了SpringMvc MultipartFile实现图片文件上传示例,具有一定的参考价值,感兴趣的小伙伴们可以参考一下。
    2017-02-02
  • java动态代理(jdk与cglib)详细解析

    java动态代理(jdk与cglib)详细解析

    静态代理:由程序员创建或特定工具自动生成源代码,再对其编译。在程序运行前,代理类的.class文件就已经存在了
    2013-09-09
  • SpringMVC Hibernate与JPA使用教程

    SpringMVC Hibernate与JPA使用教程

    这篇文章主要介绍了SpringMVC Hibernate与JPA,在正式进入Hibernate的高级应用之前,需要了解声明是数据模型与领域模型,这两个概念将会帮助我们更好的理解实体对象的关联关系映射
    2022-12-12
  • 浅谈Java中的桥接方法与泛型的逆变和协变

    浅谈Java中的桥接方法与泛型的逆变和协变

    对应于Java当中,协变对应的就是<? extends XXX>,而逆变对应的就是<? super XXX>,本文详细的介绍了Java中的桥接方法与泛型的逆变和协变,感兴趣的可以了解一下
    2022-04-04
  • java暴力匹配及KMP算法解决字符串匹配问题示例详解

    java暴力匹配及KMP算法解决字符串匹配问题示例详解

    这篇文章主要为大家介绍了java算法中暴力匹配算法及KMP算法解决字符串匹配的问题示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步
    2021-11-11
  • Java实现通过IP获取IP归属地的方法(离线+在线)

    Java实现通过IP获取IP归属地的方法(离线+在线)

    我们都知道安全攻击都是在某台客户机上执行某些恶意操作致使服务端响应异常崩溃亦或响应数据被篡改,首先我想到的是对访问的web端做一个IP的校验,那么我们首先得知道客户端的IP是多少,接下来此文重点介绍如何获得,需要的朋友可以参考下
    2023-10-10
  • SpringBoot整合RocketMQ的详细过程

    SpringBoot整合RocketMQ的详细过程

    这篇文章主要介绍了SpringBoot整合RocketMQ的详细过程,本文分为三部分,第一部分实现SpringBoot与RocketMQ的整合,第二部分解决在使用RocketMQ过程中可能遇到的一些问题并解决他们,第三部分介绍如何封装RocketMQ以便更好地使用,需要的朋友可以参考下
    2023-04-04
  • Java实现堆算法的使用示例

    Java实现堆算法的使用示例

    本文主要介绍了Java实现堆算法的使用示例,Java中提供了一个Heap类,可以用来实现堆的操作,可以实现如插入、删除、获取最大最小值等,具有一定的参考价值,感兴趣的可以了解一下
    2023-12-12

最新评论