服务器环境8核 32G内存

问题:

在5000个连接的时候Tomcat内存基本吃满

Tomcat 压测:

连接数

内存消耗

CPU

1000

6.9G

100%

2000

12G

100%

3000

19G

100%

4000

25G

100%

4468

30G

100%

更多连接已经无法建立

检查下JVM内存使用情况,其中老年代被占用了98.4%,有大量不能释放的对象在heap。

老年代内存大小31.5G,老年代使用31G

JETTY压测

连接数

内存消耗

CPU

1000

1G

25%

3000

1G

25%

5000

1.1G

25%

10000

1.2G

25%

20000

1.4G

50%

内存情况老年代被使用了79.4%,老年代总大小3.5G占用0.5G

通过现象我们可以看到jetty占用内存非常小,而TOMCAT暂用却非常多,但是国外论坛有人Tomcat却可以压到4万的连接,是什么东西占用了这么多heap空间呢?

分析TOMCAT内存占满原因:

一,由于测试方便在本地启动程序建立了501个连接,并且用jmap生成了快照

二,我们用mat来分析下内存的情况(也可以用jhat,但是太low了很多还需要人工肉眼看和计算)

我们可以看到WsFrameServer占用了2.9的heap空间对象个数恰好是我们建立的连接数

三,现在我们来分析WsFrameServer对象,到底什么东西可以占用这么大

我们可以看到WsFrameServer对象直接引用对象的heap空间HeapCharBuffer和HeapByteBuffer非常大

我们再来看看这个大对象什么引用在引用,通过分析我们知道了原来是WsFrameServer的messageBufferText成员变量

下面我们来看下源代码

我们在WsFrameServer的父类中发现了这两个大对象的引用

那么问题来了,是什么原因导致这个对象很大的呢?我们继续看源代码什么地方用来它,特别是初始化的时候

我们检查到,这个地方初始化的,初始化大小是wsSession.getMaxBinaryMessageBufferSize()

和wsSession.getMaxTextMessageBufferSize(),那么问题又来了,这两个值有是从哪里来的呢?

我们查看源码

有一个默认值是8K,如果是8K的话内存不至于溢出,看什么地方做了赋值

原来是这个地方做的赋值,那么webSocketContainer又是从哪里来的呢?

我们点进去

这里要么是默认值,要么是什么地方做了设置我们打断点调试,而且这个默认值是8K,肯定是什么地方修改了,那么我们在set方法打断点

断点来了,我们通过线程栈来分析下什么地方调到这里来的,跟着往上点

最后我们发现是这个类ServletServerContainerFactoryBean,这个类是spring提供的,我们是在这儿用到了,原来如此,内存之所以这么大就是这里的设置导致的,这个设置的目的是让websocket可以传输更大的消息

其实我们看到的Tomcat的webSocketContainer是实现了javax.websocket.webSocketContainer的,很明显这个是J2EE的规范我们可以查下这个规范

https://docs.oracle.com/javaee/7/api/javax/websocket/WebSocketContainer.html

其实这个类就是在初始化的时候可以让你设置websocket相关的一些参数

但是它设置了之后对所有session都生效了所以导致我们的连接数上不去,有什么办法可以解决吗,我们查到有另外的J2EE规范可以在运行过程中动态的修改而且是针对特定session的

那么问题来了,为什么jetty没有出现这个问题,如果是J2EE的规范那么我们设置这个值JETTY也应该出现这个问题,可是没有!

我们再来对jetty进行调试,发现这个配置对jetty不起作用

为什么不起作用呢?这又是另外的问题了~

后来通过源码分析得知JETTY和TOMCAT的实现不一样,不知道算不算BUG,个人认为是JETTY的BUG~

什么代码实现导致他们不一样呢?

Tomcat每次请求过来时在创建session时都会把这个webSocketContainer作为参数传进去所以对所有的session都生效了

我们来看看jetty

启动初始化时jetty把webSocketContainer的参数值设置给了这个过滤器,我们看看这个过滤器它的dofilter方法

其实在这个过滤器我们没有注册任何的访问URL,因为我们是通过spring提供的方式实现的websocket,如果我们在这个过滤器注册了访问URL那么所有过来的请求都会生效~可以继续跟后面的代码,其实就是调用的其他处理器来处理,这些处理器是在这里初始化的

每个url都有一个单独的处理器,这个实现是springboot提供的

spring给每一个websocket URL单独new 了一个处理器,jetty里面这个类是WebSocketServerFactory

其实jetty的处理方式是事件驱动模式设计,把所有的请求当做一个事件,不同的事件有自己对应的eventdriver来处理

重点是jetty在实例化这个对象的时候并没有把webSocketContainer所带的参数设置进去

这就导致了Tomcat生效jetty没有生效,其实你还会发现虽然jetty的buffer默认大小是64K,Tomcat是8K,可是jetty压测的时候CPU和内存都比Tomcat少,这是为什么呢?

原因是jetty用了对象池,不像tomcat来一次请求就new一个buffer,下面是jetty使用对象池的地方

后面简单做了netty的压测10000个连接消耗内存190M,吊炸天的存在

TOMCAT websocket 多连接内存泄漏与jetty对比分析相关推荐

  1. oracle11g ora 29927,【案例】Oracle内存泄漏 进行10046跟踪分析07445导致数据库宕机

    天萃荷净 在一次ORA-7445导致oracle数据库down掉故障分析中,发现sql因某种原因导致大量的sql area中很多内存泄露,最终导致数据库down掉.通过实验找出类此奇怪SQL. SEL ...

  2. Valgrind ---内存调试,内存泄漏检测以及性能分析的软件开发工具

    Valgrind是一款用于内存调试.内存泄漏检测以及性能分析的软件开发工具.Valgrind这个名字取自北欧神话中英灵殿的入口. 一般使用方式  valgrind --leak-check=full ...

  3. flv直播流播放视频,websocket响应造成内存泄漏 浏览器崩溃

    项目现状: 问题:公司做了个监控设备的直播流大屏,技术使用了flv 和websocket,项目写好了,拿到他们那边使用运行了40分钟 浏览器崩溃了,报内存不足 ## 解决思路一:第一个我想到的是flv ...

  4. 内存泄漏分析_调查内存泄漏第2部分–分析问题

    内存泄漏分析 这个小型系列的第一个博客介绍了如何创建一个非常泄漏的示例应用程序,以便我们可以研究解决服务器应用程序上基于堆的问题的技术. 它展示了Producer-Consumer模式的一个大问题,即 ...

  5. 调查内存泄漏第2部分–分析问题

    这个小型系列的第一个博客介绍了如何创建一个非常泄漏的示例应用程序,以便我们可以研究解决服务器应用程序上基于堆的问题的技术. 它展示了Producer-Consumer模式的一个大问题,即消费者代码必须 ...

  6. Android应用内存泄漏的定位、分析与解决策略

    Hello,大家好,我是Clock.翻了一下简书,发现有一个多月没有更新博客,本来今天打算和妹纸去电影院看<你的名字>,然后再去到处浪的. 结果因为妹纸公司临时有事,她不得不回公司一趟.. ...

  7. Java 内存泄漏监控检测与分析

    文章目录 1.获得转储文件 1.自动dump内存泄漏文件 2.手动dump Java的内存文件 2.MAT的使用 3.内存泄漏分析实战 1.获得转储文件 1.自动dump内存泄漏文件 在运行时加上参数 ...

  8. Java Review - 线程池中使用ThreadLocal不当导致的内存泄漏案例源码分析

    文章目录 概述 Why 内存泄露 ? 在线程池中使用ThreadLocal导致的内存泄漏 概述 ThreadLocal的基本使用我们就不赘述了,可以参考 每日一博 - ThreadLocal VS I ...

  9. Javascript 内存(三):内存泄漏常见场景及分析

    前言 内存泄漏问题,对于 Web H5 开发者来说,因为每次刷新页面,浏览器就会将当前页面的内存进行释放,影响较小.但是,对于持续不间断执行的程序,比如Nodejs.如果存在内存泄漏问题,那么内存占用 ...

最新文章

  1. 基于Spark ALS算法的个性化推荐
  2. 141 springmvc中 转发 与 重定向
  3. [USACO06DEC]牛的野餐Cow Picnic DFS
  4. PHP 与Python 读取大文件的区别
  5. 用Tkinter的Cancas实现一个写字板
  6. 基础知识(十三)dlib python人脸检测 特征点定位
  7. linux程序流量平滑,Linux下按程序查实时流量 network traffic(示例代码)
  8. 一刷leetcode——树
  9. 在训练CNN时,loss稳定在log(类别数)
  10. 刘汝佳小白书-最长回文字串
  11. ABBYY15版无水印免费Pdf编辑器
  12. MacBook快捷键
  13. 2021年2月程序员工资统计,平均15144元
  14. 全面对战LILO 和 GRUB
  15. 利用OneDNS同步chrome数据
  16. 从0开始制作H5直播源码的教程
  17. 电子合同是什么意思,电子合同怎么签才有效?
  18. PostgreSQL之外键约束
  19. Learning to See in the Dark
  20. 总结十二:管理经验法则和名言

热门文章

  1. SharePoint上传循环添加label并获取上传文件名字的扩展名和文件大小(Session[demo] = new ListLabel();方法实现)...
  2. SQL Cookbook:一、检索记录(13)按模式搜索
  3. SCUT - 337 - 岩殿居蟹 - 线段树 - 树状数组
  4. 系统服务及shell编程
  5. margin塌陷问题
  6. python实现文件夹增量同步
  7. 转载---SQL Server XML基础学习2之--FOR XML AUTO/RAW
  8. ZOJ 1610 Count the Colors (线段树区间更新)
  9. 【struts2】struts2的一些常用高级应用
  10. 美国读本科出勤率低被休学,无法毕业怎么办