SpringCloud处理Websocket消息过长自动断开连接?
最近发现Websocket发送超过6w个字节的时候就会自动断开连接,前端控制台没有报错信息,Websocket后端也没有报错信息,这就迷了。网上一搜,方案大致两种:消息分片和调整消息限制长度。消息分片不考虑,那么只有调整消息限制长度的方案。
1、调整tomcat容器的限制
在Websocket的配置中,定义Container的配置。
@Configuration
@EnableWebSocket
public class WebsocketConfiguration implements WebSocketConfigurer {
private static final int MAX_MESSAGE_SIZE = 20 * 1024;
private static final long MAX_IDLE = 60 * 60 * 1000;
@Bean
public ServletServerContainerFactoryBean createServletServerContainerFactoryBean() {
ServletServerContainerFactoryBean container = new ServletServerContainerFactoryBean();
container.setMaxTextMessageBufferSize(MAX_MESSAGE_SIZE);
container.setMaxBinaryMessageBufferSize(MAX_MESSAGE_SIZE);
container.setMaxSessionIdleTimeout(MAX_IDLE);
return container;
}
}
但是还是没有起到作用,Websocket依然断开。
注意:MAX_MESSAGE_SIZE不应设置过大,否则建立连接频繁申请过大的空间容易导致内存溢出
参考:websocket影响内存泄漏的两个点
TOMCAT websocket 多连接内存泄漏与jetty对比分析
2、调整Gateway转发对消息长度的限制
在排查日志的时候,发现Spring Cloud Gateway报错了,如下:
io.netty.handler.codec.CorruptedFrameException: Max frame length of 65536 has been exceeded.
这Gateway也来插一脚,大致就是推送的消息长度不能超过65536字节。
具体解决方法,上网了一下,参考https://blog.csdn.net/wu_xijie/article/details/103166605。Websocket发送消息没有再断开,但只解决了发送期间消息长度的问题,在Websocket建立连接的时候,发送的消息超过6w个字节照样出错。
3、调整netty建立时候消息长度的限制
这个和上面的解决不一样,替换初始化的Bean比较困难,最后通过修改源码来进行调整长度的限制。主要修改的是HttpServerWSOperations这个类的初始化时,增加WebSocketServerHandshakerFactory 的maxFramePayloadLength的参数。修改完后,重新打包,覆盖原来项目依赖的Jar包。
4、最后
其实,如果你不是一定要Gateway来转发Websocket的话,可以直接用nginx转发Websocket到对应的服务,那就没有Gateway转发限制的烦恼了。如果不用Gateway转发,那么只需要第一步设置就行了,第二第三步都不需要。
⚠️注意
新版本已经可以通过配置文件来修改这个值:spring.cloud.gateway.httpclient.websocket.max-frame-payload-length