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

Dubbo服務內存溢出,沒法建立本地線程問題的解決方案java

異常狀況

項目使用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中;bash

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的配置知足不了微服務的需求,因此發生了該緣由。socket

一樣類似的問題有,在多個微服務中單獨使用數據庫線程池,鏈接同一個數據庫,形成鏈接池溢出。微服務

 

解決方法有幾種:工具

  1. l   將Dubbo服務使用Dubbo推薦的打包方式,構建成獨立的.jar程序,每一個服務單獨啓動,獨享JVM。
  2. l   修改Tomcat的MaxThread知足線程數量要求(不推薦,Tomcat線程數也不是無限的,並且基於操做系統,Window中一個進程能夠開啓大約2000個線程,Linux中默認一個進行只能開啓1000個線程);
  3. l   修改Dubbo的配置,合理設置線程池的駐留線程數量;

相關文章
相關標籤/搜索