达到Java线程下限(503个线程)

达到Java线程下限(503个线程),java,multithreading,memory-leaks,out-of-memory,systemd,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(Jerse

我还有一个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]
环境详情:

  • AWS t2.2中等EC2实例
  • Java(TM)SE运行时环境(构建1.8.0_111-b14),带有Java热点(TM)64位服务器VM(构建25.111-b14,混合模式)。也在u211更新中复制
  • 使用SLES 15
  • 我的测试服务器上有4 GB
  • 在生产服务器上看到类似的结果,该服务器是一个t2.5的大型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
    
    意见:

  • 似乎是网络IO线程导致了此问题。有许多线程池负责各种应用程序逻辑,它们很好。只是在进行大量网络I/O时,才会创建更多的线程(取决于负载),这就是问题出现的时候
  • 应用程序的限制似乎是503个线程(由VisualVM和JConsole报告)。如果我们加载测试并保持在503线程以下,一切都很好。如果我们点击503个线程,那么我们会收到OOM消息,并且不会创建更多的线程。这远远低于正常的线程/进程限制,而正常的线程/进程限制会在类似的问题中出现。此外,在某些线程泄漏场景中,我们不会创建1000个线程。我们实际上是在故意创建>503个线程
  • 可在
    -Xss
    设置为默认值(1MB)、
    512k
    2M
    的情况下复制-所有变化都在503个线程处结束,即这似乎不是物理内存限制,而是一些计数器限制
  • top
    报告的内存使用率没有超过~70%
  • 我可以提供线程转储和NMT输出,但它们似乎并没有显示任何异常。它们只显示503个现有线程和堆分配等

    我看到的所有问题都与:

  • 实际、错误的螺纹泄漏或
  • 具有1000个线程的合法情况
  • 非常小的
    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上受支持。这意味着我们不能仅为我们的服务设置不同的限制,而必须为所有服务设置全局限制。

    系统上同时运行的其他进程有多少?每个线程消耗一个pid,您可能达到了内核限制。
    /proc/sys/kernel/pid_max
    的值是多少?这与你从
    ps-AL——无标题| wc-l
    中得到的值相比如何?
    ps-AL——无标题| wc-l
    得到765,而
    sudo lsof-Ki | wc-l
    得到3672。我们认为,我们可能遇到了这里描述的相同问题:您应该将此作为问题的答案。