测试在进行一次性能测试的时候发现并发300个请求时出现了下面的异常:java
HTTP Status 500 - Handler processing failed; nested exception is java.lang.OutOfMemoryError: unable to create new native threadajax
看到这个异常有点发慌,毕竟并发程序写的少,忽然来这么一个确实有点找不着背。但无论怎么样仍是先搜索一下是啥缘由吧。tomcat
这个错误是由于没法再建立新线程致使的,缘由多是没有更多的空间用于建立线程,还有一个公式用来计算:服务器
(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads多线程
这其中各个参数的意思是:
MaxProcessMemory:进程最大寻址空间。
JVMMMEMORY:jvm的内存空间(堆+永久区)-Xmx大小 (应该是实际分配大小)
ReservedOsMemory:操做系统预留内存
ThreadStackSize:-Xss大小并发
懒得写了,找一篇参考:https://my.oschina.net/xinxingegeya/blog/744462jvm
因而我查看一下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方式监控了。链接上后再进行测试问题缘由找到了。
线程产生这么大主要是两块:
一、tomcat的自己须要支持并发的线程
二、smack产生的大量线程,并且连续压测会发现smack的线程出现不释放的状况
这里的关键是smack的使用,由于系统实现了一个功能就是经过网页发起ajax请求,而后在服务端模拟即时经过用户发送消息。由于并发300个请求,致使每一个请求都要建立smack的链接,而smack是用于客户端开发的库,启动后会建立3个左右的线程用于链接和处理服务器的通信。这就致使同时会产生300*3的线程,因此并发时会所线程建立数用满。
既然问题缘由找到了,因此这里的问题可能仍是smack的使用问题,毕竟smack是个客户端库,不太适合于这种服务端的场景。
解决方法是使用其余方式代替smack发消息,这样只须要建立少许的线程就能够知足要求,并且处理速度大大提高。