解决java.lang.OutOfMemoryError: unable to create new native thread

Dubbo服务内存溢出,无法创建本地线程问题的解决方案

异常情况

项目使用Dubbo微服务框架开发后端服务。在服务开启后一小时左右,开始拒绝服务并循环抛出该异常:

com.alibaba.dubbo.remoting.ExecutionException: class com.alibaba.dubbo.remoting.transport.dispatcher.all.AllChannelHandler error when process caught event .

           at com.alibaba.dubbo.remoting.transport.dispatcher.all.AllChannelHandler.caught(AllChannelHandler.java:67)

           at com.alibaba.dubbo.remoting.transport.AbstractChannelHandlerDelegate.caught(AbstractChannelHandlerDelegate.java:44)

           at com.alibaba.dubbo.remoting.transport.AbstractChannelHandlerDelegate.caught(AbstractChannelHandlerDelegate.java:44)

           at com.alibaba.dubbo.remoting.transport.AbstractPeer.caught(AbstractPeer.java:127)

           at com.alibaba.dubbo.remoting.transport.netty.NettyHandler.exceptionCaught(NettyHandler.java:112)

           at com.alibaba.dubbo.remoting.transport.netty.NettyCodecAdapter$InternalDecoder.exceptionCaught(NettyCodecAdapter.java:165)

           at org.jboss.netty.channel.Channels.fireExceptionCaught(Channels.java:432)

           at org.jboss.netty.channel.AbstractChannelSink.exceptionCaught(AbstractChannelSink.java:52)

           at org.jboss.netty.channel.Channels.fireChannelDisconnected(Channels.java:360)

           at org.jboss.netty.channel.socket.nio.NioWorker.close(NioWorker.java:593)

           at org.jboss.netty.channel.socket.nio.NioWorker.read(NioWorker.java:356)

           at org.jboss.netty.channel.socket.nio.NioWorker.processSelectedKeys(NioWorker.java:280)

           at org.jboss.netty.channel.socket.nio.NioWorker.run(NioWorker.java:200)

           at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1145)

           at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:615)

           at java.lang.Thread.run(Thread.java:745)

Caused by: java.lang.OutOfMemoryError: unable to create new native thread

           at java.lang.Thread.start0(Native Method)

           at java.lang.Thread.start(Thread.java:714)

           at java.util.concurrent.ThreadPoolExecutor.addWorker(ThreadPoolExecutor.java:949)

           at java.util.concurrent.ThreadPoolExecutor.execute(ThreadPoolExecutor.java:1360)

           at com.alibaba.dubbo.remoting.transport.dispatcher.all.AllChannelHandler.caught(AllChannelHandler.java:65)

           ... 15 more

问题分析过程

1.        分析异常信息,发现无法创建新的线程;

2.        了解微服务部署架构,发现共六个微服务,都部署在一个Tomcat中;

3.        打开JDK自带的分析工具,jvisualvm.exe,该程序在JAVA_HOME\bin目录下,载入Tomcat查看线程情况,发现Tomcat的MaxThread设置在800;

4.        通过dubbo的status命令,发现服务的线程池配置为固定200个连接,6个服务需要1200个连接,超过了Tomcat的MaxThread,所以Tomcat无法创建新线程;

问题原因与解决方案

项目将Dubbo微服务打包成.war程序,放在Tomcat容器中,借助Tomcat启动微服务,使用Tomcat的JVM。由于放在该Tomcat中的微服务过多,Tomcat的配置满足不了微服务的需求,所以发生了该原因。

同样相似的问题有,在多个微服务中单独使用数据库线程池,连接同一个数据库,造成连接池溢出。

解决方法有几种:

  1. l   将Dubbo服务使用Dubbo推荐的打包方式,构建成独立的.jar程序,每个服务单独启动,独享JVM。
  2. l   修改Tomcat的MaxThread满足线程数量要求(不推荐,Tomcat线程数也不是无限的,而且基于操作系统,Window中一个进程可以开启大约2000个线程,Linux中默认一个进行只能开启1000个线程);
  3. l   修改Dubbo的配置,合理设置线程池的驻留线程数量;

猜你喜欢

转载自my.oschina.net/u/2450666/blog/1818934