记一次WebSocket的MaxTextMessageBufferSize值设置过大引发的问题

问题

项目中用WebSocket作为客户端,接收其他厂商的数据。出现数据处理延迟的情况。前面博客中已经说到,增加线程处理数据可以解决延迟。但是在反复调试中发现,除了增加线程以外,还有一个因素影响数据的延迟,如下:

 wsWebSocketContainer.setDefaultMaxBinaryMessageBufferSize(51200000);
 wsWebSocketContainer.setDefaultMaxTextMessageBufferSize(51200000);

这个参数的设置,也会影响数据的延迟。在服务器上,当设置为51200000及以下时,数据不会延迟。当设置成512000000时,数据就出现了延迟,当设置成2048000000时,数据又不延迟了。这真是一个神奇的现象。
在本地开发环境中,当设置为512000000时,也不会延迟。

解决历程

一般情况下,这个参数设置的越大,缓存数据越多,消费性能越好,这是我们默认的想法,所以最初设置成了512000000。那照这个思路,继续增大这个参数值,改成2048000000,就不延迟了,这也符合预期。但是为什么缩小这个参数,改成51200000也不延迟呢?这就很奇怪了。而且为何在服务器上设置512000000就延迟,同样的代码,在本地环境就不延迟呢?
起初的猜测是,服务器TCP参数需要调优,服务器是Window Server 2019系统,本地开发环境是Windows 10系统。可能因为服务器的TCP参数导致。对着百度一顿调优后发现,并没有用,还是同样的问题。
这个问题困扰很久之后,在一次偶然的日志查阅中,看到了关键日志:Out Of Memory。
因为日志信息很大,而这行信息只占用了其中一行,所以,在很久之后,才在茫茫日志中看到了这条重要的信息。
于是打开了jdk监测工具,下图是三个参数值下的内存情况:
2048000000:
在这里插入图片描述

512000000:
在这里插入图片描述
51200000:
在这里插入图片描述

问题得到了解决。首先,参数是2048000000时,项目启动后,内存直接到了8G,说明设置的值很大,内存一下提升上来。过了会儿后,为何内存又降低了呢。因为内存飙升到8G后,消息已经处理不过来了,WebSocket客户端有这种机制,当消息消费不过来后,积压很多后,会断开WebSocket链接。因为项目中有重连的逻辑,所以,断开连接后,又第二次进行了WebSocket的连接。此时看日志可以发现,此时缓冲区的大小,已经不是2048000000了,而变成了5120000。这个值是重连时重新设置的值。所以,当缓冲区容量小后,内存就不爆满了,消息也就可以正常处理了,所以,值设置的太大,是因为消息积压造成断开后重连,自动缩小了缓冲区的值,数据不再延迟了。

然后,分析值是512000000时,为何服务器上延迟,本地不延迟?本地不延迟的道理和2048000000道理一样,因为消息处理不过来了,内存爆满,断开重连了,缩小了缓冲区的空间,不延迟了。而在服务器上,服务器配置比本地高,所以,512000000这个值,也造不成WebSocket消息积压的断开,但是内存占用却很高,已经影响了处理速度了,也就是说,它处于一种消息处理不过来,但是又不至于断开的状态,所以,就出现延迟了。

最后,设置成51200000时,此时由图可知,内存占用是很小的,而且会定时清理,此时,就可以正常消费数据,不延迟了。

由上面的分析可知,MaxTextMessageBufferSize这个值,不能过大,不是越大越好,而是要根据内存等因素,来设置。

通过这个bug,还需要有的经验就是,下次再次遇到类似的情况时,可以想到是内存方面的因素造成的。因素缓冲区值调大后,首当其冲的就是内存的压力增大。有了这方面意识,下次不至于在找不到日志时没有思路乱猜测了。

源码追踪

因为WebSocket客户端经常用于浏览器端,这种在java中使用WebSocket客户端接收消息的场景属实不多,所以这里不对WebSocket客户端原理深入追踪,直接把断点点在onclose方法上,进行倒推,看什么情况触发了它的onclose方法。
通过倒推,最终定位到了如下信息:
在这里插入图片描述
WebSocket使用了NIO技术ByteBuffer类来接收数据,ByteBuffer使用了堆外内存。所以,报出了Direct buffer memory异常,而不是jvm堆内异常。这也是为啥很难找到异常的原因。堆外异常,不影响jvm的使用,所以报错信息很少。所以,MaxTextMessageBufferSize设置过大后,影响了堆外内存,造成了客户端的断开。
由此可见,NIO技术和ByteBuffer值得研究,以后有机会进行深入了解和研究。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
THE END
分享
二维码
< <上一篇

)">
下一篇>>