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



我还有一个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(TM) SE 运行时环境(内部版本 1.8.0_111-b14),使用 Java HotSpot(TM) 64 位服务器虚拟机(内部版本 25.111-b14,混合模式)。也转载于更新 u211。
  3. 使用 SLES 15。
  4. 测试服务器上有 4 GB
  5. 在生产服务器上看到类似的结果,该服务器是 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值。

这些都不适用于我的情况。

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

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

事实证明这是一个系统问题。

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

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

/etc/systemd/system.conf中设置DefaultTasksMax=infinity解决了这个问题(这确实需要重新启动我们的盒子)。

我们实际上正在运行一个initd服务,该服务通过systemctl在systemd上得到支持。这意味着我们不能只为我们的服务设置不同的限制,而必须为所有服务设置全局限制。

最新更新