SpringCloud处理Websocket消息过长自动断开连接
问题描述
近期实现了客户端订阅
Websocket
后,服务端定期向客户端推送相关设备消息的功能,在本地测试没有问题,上线后却发现订阅设备数量超过一定数量后Websocket
就会自动断开连接
报错日志
tex
java.lang.IllegalStateException: Message will not be sent because the WebSocket session has been closed
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.writeMessagePart(WsRemoteEndpointImplBase.java:449) ~[tomcat-embed-websocket-9.0.79.jar:9.0.79]
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:307) ~[tomcat-embed-websocket-9.0.79.jar:9.0.79]
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendMessageBlock(WsRemoteEndpointImplBase.java:249) ~[tomcat-embed-websocket-9.0.79.jar:9.0.79]
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendString(WsRemoteEndpointImplBase.java:191) ~[tomcat-embed-websocket-9.0.79.jar:9.0.79]
at org.apache.tomcat.websocket.WsRemoteEndpointImplBase.sendObject(WsRemoteEndpointImplBase.java:614) ~[tomcat-embed-websocket-9.0.79.jar:9.0.79]
at org.apache.tomcat.websocket.WsRemoteEndpointBasic.sendObject(WsRemoteEndpointBasic.java:72) ~[tomcat-embed-websocket-9.0.79.jar:9.0.79]
at tbea.websocket.SubscribeDeviceParamWebSocketServer.lambda$scheduleMessagePush$2(SubscribeDeviceParamWebSocketServer.java:305) ~[classes/:na]
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[na:1.8.0_301]
at java.util.concurrent.FutureTask.runAndReset$$$capture(FutureTask.java:308) ~[na:1.8.0_301]
at java.util.concurrent.FutureTask.runAndReset(FutureTask.java) ~[na:1.8.0_301]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) ~[na:1.8.0_301]
at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) ~[na:1.8.0_301]
at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) ~[na:1.8.0_301]
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) ~[na:1.8.0_301]
at java.lang.Thread.run(Thread.java:748) ~[na:1.8.0_301]
问题排查
经过排查发现当Websocket
服务段推送消息数据大小在50kb左右时功能正常,此时再增加订阅一个设备时,线上Websocket
就会自动断开连接,这时候很容易想到可能是Websocket
推送消息可能又大小限制,当消息超过64kb的时候可能会自动断连。
然而我在本地测试发现消息数据大小远远超过64kb,仍然没有断连,客户端依旧可以收到消息。
这时发现我本地测试时,直接调用的是提供该功能服务的端口,而线上调用的是网关(gateway),再次测试发现,通过网关订阅Websocket
时消息数据大小超过64kb时确实会自动断连。
解决方法
知道问题原因之后,直接通过搜索引擎发现Spring Cloud Gateway
可以通过spring.cloud.gateway.httpclient.websocket.max-frame-payload-length
配置来修改消息体的大小限制
修改gateway
配置文件如下:
yaml
spring:
cloud:
gateway:
httpclient:
websocket:
# websocket数据包最大字节数
max-frame-payload-length: 6553600
修改配置文件后,重新部署gateway
发现功能正常。