记一次tomcat线程创建异常调优:unable to create new native thread

测试在进行一次性能测试的时候发现并发300个请求时出现了下面的异常:

HTTP Status 500 - Handler processing failed; nested exception is java.lang.OutOfMemoryError: unable to create new native thread

看到这个异常有点发慌,毕竟并发程序写的少,突然来这么一个确实有点找不着背。但不管怎么样还是先搜索一下是啥原因吧。

这个错误是因为无法再创建新线程导致的,原因可能是没有更多的空间用于创建线程,还有一个公式用来计算:

(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads

这其中各个参数的意思是: MaxProcessMemory:进程最大寻址空间。 JVMMMEMORY:jvm的内存空间(堆+永久区)-Xmx大小 (应该是实际分配大小) ReservedOsMemory:操作系统预留内存 ThreadStackSize:-Xss大小

懒得写了,找一篇参考:https://my.oschina.net/xinxingegeya/blog/744462

于是我查看一下liunx系统的参数情况:

[root@RHEL63temp ~]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 63628
max locked memory       (kbytes, -l) 64
max memory size         (kbytes, -m) unlimited
open files                      (-n) 1024
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 1024
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

其中的max user processes只有1024个,心想着这事情可能问题不在于创建的限制,而是为什么要创建这么多线程?毕竟只有300个并发,tomcat最多也就300个线程用于处理请求吧?

于是想了想程序代码的问题,还是要从代码上去查找原因。于是临时开始研究了一下JVisualVM这个监控工具,在服务器上做了做配置,反正网上有教程。因为我使用的是Tomcat,所以直接就监控Tomcat吧,在catalina.sh中增加一些参数:

JAVA_OPTS="-server -Xmx384m -Xms128m -XX:PermSize=128M -XX:MaxPermSize=256m"
	-Dcom.sun.management.jmxremote.port=9998 
	-Dcom.sun.management.jmxremote.ssl=false 
	-Dcom.sun.management.jmxremote.authenticate=false 
	-Djava.rmi.server.hostname=192.168.49.199"

这样就可以使用JVisualVM通过JMX方式监控了。连接上后再进行测试问题原因找到了。

线程产生这么大主要是两块: 1、tomcat的本身需要支持并发的线程 2、smack产生的大量线程,而且连续压测会发现smack的线程出现不释放的情况

这里的关键是smack的使用,因为系统实现了一个功能就是通过网页发起ajax请求,然后在服务端模拟即时通过用户发送消息。因为并发300个请求,导致每个请求都要创建smack的连接,而smack是用于客户端开发的库,启动后会创建3个左右的线程用于连接和处理服务器的通讯。这就导致同时会产生300*3的线程,所以并发时会所线程创建数用满。

既然问题原因找到了,所以这里的问题可能还是smack的使用问题,毕竟smack是个客户端库,不太适合于这种服务端的场景。

解决方法是使用其他方式代替smack发消息,这样只需要创建少量的线程就可以满足要求,而且处理速度大大提升。

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏北京马哥教育

一图掌握bash shell编程

? 一张图掌握bash shell编程, 总结自 The Linux Command Line Ch25~Ch37. PDF版本下载请查看: 链接: http...

3298
来自专栏散尽浮华

Centos下添加静态路由(临时和永久有效)的操作记录

公司IDC机房服务器上部署了一套外网LB环境,默认配置的是外网ip的路由地址,由于要和其他内网机器通信,所以需要配置内网ip的路由地址。整个操作过程,记录如下,...

2219
来自专栏积累沉淀

centos7 mysql数据库安装和配置

一、系统环境 yum update升级以后的系统版本为 [root@yl-web yl]# cat /etc/redhat-release CentOS Li...

4688
来自专栏Go 语言编程

aurora - 跨平台 Beanstalk 消息队列服务器管理工具

aurora 是一个基于 Web 的 Beanstalk 消息队列服务器管理工具,单文件无需依赖其他组件,支持管理本地和远程多个队列服务器。

5977
来自专栏Petrichor的专栏

ubuntu: scp指令 (远程拷贝)

用于在Linux下进行远程拷贝文件的命令,和它类似的命令有cp,不过cp只是在本机进行拷贝不能跨服务器,而且scp传输是加密的。当你服务器硬盘变为只读 read...

2972
来自专栏三杯水

Centos7.4部署配置Elasticsearch6.3.2集群

https://www.elastic.co/guide/cn/elasticsearch/guide/current/important-configurat...

3603
来自专栏电光石火

eclipse配置tomcat运行时访问路径不要项目名称

1:双击打开tomcat 2:选择Modules,选择你要修改的项目 ? 3:点击Edit,把path修改成空或者你自己想要的路径即可! ?

3136
来自专栏空木白博客

分享5个网址二维码API接口

它们只需要填写好网址就能自动生成二维码,分别来自与bshare和jiathis分享工具中,如您需要就把下面的二维码生成API接口复制到你需要地方。

4702
来自专栏Porschev[钟慰]的专栏

Windows Server 2008 R2 配置AD(Active Directory)域控制器

配置环境 Windows版本:Windows Server 2008 R2 Enterprise                      S...

5245
来自专栏埋名

CentOS7安装维护Gitlab

下面是官网复制过来的官方安装方法,最简单的安装,在我大天朝,只能望天兴叹,你可翻墙安装或者略过这里,看下面的。

5713

扫码关注云+社区

领取腾讯云代金券