最近發現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
