基于springboot编写了一个简单Websocket服务,主要用来接收客户端上报的各种数据。由于网络环境不稳定,经常出现websocket连接中断,客户端自动重连的现象。
某日,生产环境突然出现上百个客户端集体掉线的警报,而且是同一时间发生的,平常也就一两个掉线告警。
起初以为是网络问题,但从客户端现象看,一直时连接超时,网络可以ping通。搜索后台日志,发现大量connection reset异常,并伴有OutOfMemoryError: java heap space (先重启解决离线了问题)
想办法在本地重现:调整JVM -Xms500M -Xmx500M
一个客户端,一直发送消息,通过jconsole发现,jvm堆内存并不会一直增长,大部分数据在没有进入年老代就被回收了。
连续建立多个客户端,不中断连接,很快就出现了OOM,dump内存数据,使用jvisualvm进行简要分析:
找出最大的对象,如下:竟然全部是WsFrameServer对象,继续点击去看下对象细节

主要是两个buffer占用的大量空间!
![]()
看源码,发现端倪,每初始化一个WsFrameServer对象,jvm都要分配maxBinaryMessageBufferSize和maxTextMessageBufferSize的内存,过多的websocket连接,很快就把内存沾满了。

知道了原因,也就有应对方法。减小bufferSize,设置合理的空闲超时时间。
bufferSize设置:
@Configuration
@ComponentScan
@EnableAutoConfiguration
public class WebSocketConfig implements ServletContextInitializer{
//配置websocket传输大小
@Override
public void onStartup(ServletContext servletContext) throws ServletException {
servletContext.addListener(WebAppRootListener.class);
servletContext.setInitParameter("org.apache.tomcat.websocket.textBufferSize","128000");
servletContext.setInitParameter("org.apache.tomcat.websocket.binaryBufferSize","128000");
}
}
和客户端连接建立后,配置空闲超时时间
session.setMaxIdleTimeout(10000);
再重新测试,系统的容量提高了很多(虽然无法完全避免OOM)
参考:https://www.cnblogs.com/qiantao/p/13576441.html

浙公网安备 33010602011771号