在 Spring Cloud Gateway 3.1.4 版本中配置 WebSocket 通信时,遇到 Max frame length of 65536 has been exceeded 错误。经过源码分析发现,网上流传的通过 spring.cloud.gateway.httpclient.websocket.max-frame-payload-length 配置参数修改最大帧长度的方法无效。本文通过源码解析问题根源,并提供有效解决方案。

问题现象

WebSocket 配置伪代码


typescript

体验AI代码助手

代码解读

复制代码

@Autowired @Bean public HandlerMapping webSocketMapping(final EchoHandler echoHandler) { Map<String, WebSocketHandler> map = new HashMap<>(); map.put("/echo", echoHandler); SimpleUrlHandlerMapping mapping = new SimpleUrlHandlerMapping(); mapping.setOrder(Ordered.HIGHEST_PRECEDENCE); mapping.setUrlMap(map); return mapping; } @Bean public WebSocketHandlerAdapter handlerAdapter() { return new WebSocketHandlerAdapter(); // 问题关键在这里 }

即使配置了:


yaml

体验AI代码助手

代码解读

复制代码

spring: cloud: gateway: httpclient: websocket: max-frame-payload-length: xxxxxx

仍然会触发默认最大帧长度 65536 的限制错误。

为什么配置了 max-frame-payload-length 却无效?

这要从 WebSocketHandlerAdapter 的源码开始分析。


csharp

体验AI代码助手

代码解读

复制代码

public WebSocketHandlerAdapter() { this(new HandshakeWebSocketService()); // 使用默认HandshakeWebSocketService }

HandshakeWebSocketService 的默认构造器如下:


csharp

体验AI代码助手

代码解读

复制代码

// gateway 使用的是reactor netty 所以最后初始化出来的是ReactorNettyRequestUpgradeStrategy public HandshakeWebSocketService() { this(initUpgradeStrategy()); // 初始化 ReactorNettyRequestUpgradeStrategy }

默认会使用 ReactorNettyRequestUpgradeStrategy


csharp

体验AI代码助手

代码解读

复制代码

public ReactorNettyRequestUpgradeStrategy() { this(WebsocketServerSpec::builder); // 使用无参 builder }

进一步查看 WebsocketServerSpec.Builder 的实现:


scala

体验AI代码助手

代码解读

复制代码

public static class Builder<SPEC extends Builder<SPEC>> implements Supplier<SPEC> { int maxFramePayloadLength = 65536; // 默认值 ... }

结论

Spring Cloud Gateway 的 spring.cloud.gateway.httpclient.websocket.max-frame-payload-length 配置项实际上无法修改底层 WebsocketServerSpec 的 maxFramePayloadLength 值,因为默认构造方式不会读取该配置。

有效解决方案

我们可以自己构建一个带参数的 ReactorNettyRequestUpgradeStrategy,明确设置 maxFramePayloadLength

通过显式配置 ReactorNettyRequestUpgradeStrategy 并自定义 WebsocketServerSpec


java

体验AI代码助手

代码解读

复制代码

@Bean public WebSocketHandlerAdapter handlerAdapter() { int frameSizeLimit = 655360; // 设置为你所需的帧长度限制 WebsocketServerSpec.Builder builder = WebsocketServerSpec.builder().maxFramePayloadLength(frameSizeLimit); ReactorNettyRequestUpgradeStrategy upgradeStrategy = new ReactorNettyRequestUpgradeStrategy(builder); return new WebSocketHandlerAdapter(new HandshakeWebSocketService(upgradeStrategy)); }

补充说明

若需要配置更多 WebSocket 参数(如启用压缩、调整 Ping/Pong 处理策略),可在 WebsocketServerSpec.Builder 中链式调用:


scss

体验AI代码助手

代码解读

复制代码

WebsocketServerSpec.Builder builder = WebsocketServerSpec.builder() .maxFramePayloadLength(655360) .compress(true) // 启用压缩 .handlePing(false); // 禁止自动处理Ping帧

总结:

  • spring.cloud.gateway.httpclient.websocket.max-frame-payload-length 是 针对 gateway 客户端通信(即作为 WebSocket 客户端)配置的;

  • 如果你是通过自定义 WebSocketHandlerAdapter 来处理 WebSocket 请求(即作为 WebSocket 服务端),则必须手动指定 maxFramePayloadLength

  • 默认构造路径中的帧大小限制是写死在源码中的,必须通过构造器覆盖。

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐