2015-06-22 51 views
12

我已经看到其他对此问题的引用,例如herehere,尽管这些引用了不同版本的Netty。尝试使用4.0分支(4.0.29)和5.0 alpha分支(5.0-Alpha3)中的最新版本。本地(非Linux)jdk 1.8.040,没问题。使用java jdk 1.8.025-b17的远程(Linux)获得100%cpu。 Linux内核版本2.6.32。以100%CPU运行的Netty

使用EpollEventLoopGroup();

打过电话

workerGroup = new NioEventLoopGroup(); 
workerGroup.rebuildSelectors(); 

谁能提供任何建议试过吗?我已经看到了引用这个bug的不同版本的Netty。 JDK的bug? Netty错误?流程在启动时立即达到100%并停留在那里。

更新:升级到Java 1.8.045,相同的区别。

JStack output所有可运行的线程(里面有一些rabbitmq的东西,只是为了完整性而包含 - 这对其他应用程序来说很常见,并且不是问题的原因)。

+1

如果你可以运行'top -H -p '和'jstack ',你可以看到哪些线程使用CPU和这些线程的堆栈。我还建议运行'jstat -gc '以确保它不是内存问题。 –

+0

感谢您的建议。 top -H -p 显示使用所有cpi的1个子进程。 jstack显示了不等待的唯一东西是epollWait和java.net.SocketInputStream.socketRead0(Native Method)。 –

+0

你可以发布'top'和'jstack'的输出吗? enire jstack-output,但是对于'top'最高的5个线程就足够了。 –

回答

10

正如我们在意见中指明,所消耗的CPU线程是忙着在下面的堆栈:

"pool-9-thread-1" #49 prio=5 os_prio=0 tid=0x00007ffd508e8000 nid=0x3a0c runnable [0x00007ffd188b6000] 
    java.lang.Thread.State: RUNNABLE 
    at java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.poll(ScheduledThreadPoolExecutor.java:809) 
    at java.util.concurrent.ThreadPoolExecutor.getTask(ThreadPoolExecutor.java:1066) 
    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1127) 
    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:617) 
    at java.lang.Thread.run(Thread.java:745) 

我已成功通过创建ScheduledThreadPoolExecutor重现了类似的行为,将其配置为允许核心线程超时,并在很短的延迟时间内安排大量重复任务。它在我的机器上产生大量的CPU,并且jstack输出类似(有时更深入到poll方法中)。这段代码也再现:

ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1); 
executor.setKeepAliveTime(1, TimeUnit.MINUTES); 
executor.allowCoreThreadTimeOut(true); 
for (long i = 0; i < 1000; i++) { 
    executor.scheduleAtFixedRate(new Runnable() { 

     @Override 
     public void run() { 
     } 
    }, 0, 1, TimeUnit.NANOSECONDS); 
} 

现在,我们只需要确定哪些代码设置一个破ScheduledThreadPoolExecutor。我搜索了RabbitMQ和Netty源代码,但没有发现任何obvoius。它可能是你在自己的代码中做的事情吗?

编辑:作为评价提到的,根本原因是与0初始化的ScheduledThreadPoolExecutor这显然会导致CPU自旋OM一些平台。这是在OP的代码中完成的。

+3

不幸的是,虽然我想说别人有错,但事实上,这与我自己的代码有关。事实证明,如果你错误地用0初始化一个scheduledThreadPool,你会得到100%的CPU空转。为什么有人会那样做?上帝只知道 - 当然不是我曾经做过的事情。 在任何情况下,javadoc指定使用<0会抛出一个IllegalArgument,但不会提及0.他们可能应该抛出异常0. 感谢您的帮助,并享受+100。我要去汉堡王申请工作。 –

+0

@SteveB。很高兴我能帮上忙。有趣的事业! –

+1

有人可能会这样做的原因是因为他们希望每30分钟安排一次,但整个时间内没有为此目的分配线程(仅等待30分钟) - 因此您允许核心线程超时或甚至将核心线程设置为0 ...让它感到惭愧。 – john16384