• 记一次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发消息,这样只需要创建少量的线程就可以满足要求,而且处理速度大大提升。

     

    注:此文章为原创,欢迎转载,请在文章页面明显位置给出此文链接!
    若您觉得这篇文章还不错请点击下右下角的推荐,非常感谢!
    http://www.cnblogs.com/5207
  • 相关阅读:
    使用 Nginx 内置 $http_user_agent 来区分( 电脑 pc、手机 mobile、平板 pad )端的内容访问
    原创《开源一个用 vue 写的树层级组件 vue-ztree》
    原创《weex面向未来的架构》
    原创《如何用vue来轻松的驾驭 html5 webapp的页面体验》
    Pdf Convert Image 的解决方案
    原创《分享(Angular 和 Vue)按需加载的项目实践优化方案》
    .npmrc 实用小技巧
    使用Tampermonkey,实现Gitlab禁用自我Merge的功能
    vue 之 render 函数不能渲染非全局自定义函数-方案
    反射、注解和动态代理
  • 原文地址:https://www.cnblogs.com/5207/p/5992873.html
Copyright © 2020-2023  润新知