yunnick

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: 订阅 订阅 :: 管理 ::

基于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

 

posted on 2021-03-16 18:54  yunnick  阅读(2067)  评论(0编辑  收藏  举报