Достигнув низкого уровня потока Java (503 потока) - PullRequest
5 голосов
/ 13 июня 2019

У меня есть еще один вопрос об ограничении потоков 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 EC2instance.
  2. Среда выполнения Java (TM) SE (сборка 1.8.0_111-b14) с виртуальной машиной 64-разрядного сервера Java HotSpot (TM) (сборка 25.111-b14, смешанный режим).Также воспроизводится при обновлении u211.
  3. Использование SLES 15.
  4. 4 ГБ на моем тестовом сервере
  5. Просмотр похожих результатов на рабочем сервере, который является экземпляром t2.large EC2 (8 ГБ ОЗУ).

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. Похоже, что причиной этой проблемы являются потоки сетевого ввода-вывода.Есть несколько пулов потоков, которые заботятся о различных кусочках логики приложения, и они в порядке.Именно при выполнении большого количества операций сетевого ввода-вывода создается еще несколько потоков (в зависимости от нагрузки), и именно тогда возникает проблема.
  2. Предел для приложения составляет 503 потока (как сообщалось).VisualVM и JConsole).Если мы загрузим тест и останемся менее 503 потоков, все будет хорошо.Если мы нажмем 503 потока, мы получим сообщения OOM, и больше не будет создано ни одного потока.Это намного ниже нормальных ограничений потоков / процессов, которые возникают в аналогичных вопросах по SO.Кроме того, мы не создаем тысячи потоков в некотором сценарии утечки потоков.Мы действительно пытаемся преднамеренно создать> 503 потоков.
  3. Воспроизводимые с -Xss, установленным по умолчанию (1 МБ), 512k и 2M - все варианты заканчиваются на 503 потоках, т.е. это, кажется, неограничение физической памяти, но некоторое ограничение счетчика.
  4. Использование памяти, сообщаемое top, не превышает ~ 70%.

Я могу предоставить дамп потока и вывод NMTно они, кажется, не показывают ничего необычного.Они просто показывают 503 существующих потока и распределение кучи и т. Д.

Все вопросы, которые я видел, касаются:

  1. фактических, ошибочных утечек потоков или
  2. допустимые ситуации с тысячами потоков,
  3. довольно маленькие ulimit значения.

Ничто из этого не применимо к моей ситуации.

Я видел этот вопрос , который, казалось, указывает на то, что некоторые неясные настройки на самом деле переопределяют / накладывают ограничение меньше, чем показанное при использовании ulimit, но вопрос и ссылки касались RedHat.Есть ли где-то похожая настройка для SLES?

В принципе, я хотел бы знать - что происходит?Почему я не могу создать 504-ю тему?

1 Ответ

2 голосов
/ 13 июня 2019

Оказывается, это была системная проблема.

systemd ввел ограничение на количество потоков для одного процесса, которое по умолчанию произвольно составило 512 потоков. Я думаю, что наш предел 503 в тестировании был на самом деле

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

Установка DefaultTasksMax=infinity в /etc/systemd/system.conf решила эту проблему (для этого потребовалась перезагрузка нашей коробки).

На самом деле мы запускаем службу initd, которая поддерживается в systemd через systemctl. Это означает, что мы не могли установить другой лимит только для нашего сервиса и вынуждены были использовать глобальный лимит для всех сервисов.

...