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

posted @ 2020-02-22 14:01  Gin.p  阅读(7874)  评论(4编辑  收藏  举报