达到较低的Java线程限制(503个线程)

时间:2019-06-12 21:33:50

标签: java multithreading memory-leaks out-of-memory systemd

我还有另一个Java线程限制问题,但是我只说微不足道的500个左右的线程,而我找不到达到的限制。实际上-它似乎在503个线程的限制处发生,即,看起来创建线程504会产生可怕的结果:

javax.ws.rs.ProcessingException: java.lang.OutOfMemoryError: unable to create new native thread
        at org.glassfish.jersey.client.JerseyInvocation.submit(JerseyInvocation.java:980) [jersey-client-2.25.jar:na]
        at org.glassfish.jersey.client.JerseyInvocation.submit(JerseyInvocation.java:889) [jersey-client-2.25.jar:na]
        at org.glassfish.jersey.client.JerseyInvocation$AsyncInvoker.method(JerseyInvocation.java:669) [jersey-client-2.25.jar:na]

环境详细信息:

  1. AWS t2.medium EC2实例。
  2. 带有Java HotSpot™64位服务器VM(版本25.111-b14,混合模式)的Java™SE运行时环境(版本1.8.0_111-b14)。也在更新u211上转载。
  3. 使用SLES 15。
  4. 我的测试服务器上
  5. 4 GB
  6. 在t2.large EC2实例(8GB RAM)的生产服务器上看到类似的结果。

ulimit -a输出:

core file size          (blocks, -c) unlimited
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 15743
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) 8192
cpu time               (seconds, -t) unlimited
max user processes              (-u) 15743
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

观察:

  1. 似乎是网络IO线程导致了此问题。有很多线程池负责应用程序逻辑的各个方面,它们很好。只是在执行大量网络I / O时,才会创建更多线程(取决于负载),这才是问题所在。
  2. 该应用程序的限制似乎是503个线程(如VisualVM和JConsole所报告)。如果我们加载测试并保持在503线程以下,那就没问题了。如果我们命中503个线程,那么我们将收到OOM消息,并且不再创建任何线程。这远远低于正常线程/进程的限制,这在SO的类似问题中也存在。另外,在某些线程泄漏情况下,我们不会创建1000个线程。我们确实试图创建> 503个线程。
  3. -Xss设置为默认(1MB),512k2M的情况下可重现-所有变化都达到503个线程的峰值,即,这似乎不是物理内存限制,而是一些计数器限制。
  4. top报告的内存使用率未超过70%。

我可以提供线程转储和NMT输出,但是它们似乎并没有显示任何异常。它们只显示503个现有线程和堆分配等。

我所看到的所有问题都与之有关:

  1. 实际,错误的线程泄漏或
  2. 具有1000个线程的合法情况,
  3. 较小的ulimit值。

这些都不适合我的情况。

我确实看到了this question,这似乎表明某些晦涩的设置实际上覆盖/施加的限制小于使用ulimit所显示的限制,但问题和链接与RedHat有关。 SLES是否有类似的设置?

基本上我想知道-发生了什么事?为什么我不能创建第504个线程?

1 个答案:

答案 0 :(得分:2)

原来是系统问题。

systemd对单个进程的线程数进行了限制,默认为512个线程。我认为我们的503测试限制实际上是

  503 counted threads
+ 9 other threads not counted
= 512 thread limit.

DefaultTasksMax=infinity中设置/etc/systemd/system.conf可以解决此问题(这确实需要重新启动盒子)。

我们实际上正在运行通过systemctl在systemd上受支持的initd服务。这意味着我们不能只为我们的服务设置其他限制,而不得不诉诸所有服务的全局限制。