Сервер Tomcat не отвечает "http-nio-80-Acceptor-0" - PullRequest
1 голос
/ 03 мая 2020

У меня есть приложение с пружинной загрузкой (1.5.8.RELEASE), работающее с 5 ГБ ОЗУ. Когда я обращаюсь к API с каким-либо запросом, возвращающим огромные данные, он выдает

> Apr 30, 2020 2:01:34 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: GC overhead limit exceeded] with root cause

Ожидается указанное выше исключение, так как размер данных огромен, а приложению не хватает памяти. Но если я нажимаю API с тем же запросом, возвращающим огромные данные, мое приложение выдает следующее исключение, и приложение перестает отвечать на запросы, и мне нужно перезапускать его каждый раз. Но если я снова нажму на API с запросом, возвращающим меньшее количество данных, он будет работать отлично.

Exception: java.lang.OutOfMemoryError thrown from the UncaughtExceptionHandler in thread "http-nio-80-Acceptor-0"
Exception in thread "ContainerBackgroundProcessor[StandardEngine[Tomcat]]" java.lang.OutOfMemoryError: GC overhead limit exceeded
Apr 30, 2020 2:09:22 PM org.apache.catalina.core.StandardWrapperValve invoke
SEVERE: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: GC overhead limit exceeded] with root cause
java.lang.OutOfMemoryError: GC overhead limit exceeded

Почему он вызывает разные исключения для одного и того же запроса? Я проанализировал память, используя VisualVm, память сразу же очищалась после обработки запросов, и я убедился, что утечки памяти нет. Это как-то связано с org.apache.tomcat.jdbc.pool.DataSource(), который я использую?

Ответы [ 2 ]

2 голосов
/ 03 мая 2020

Вы получаете эту ошибку: java.lang.OutOfMemoryError: GC overhead limit exceeded

Эта ошибка возникает, когда JVM потратила слишком много времени на сборку мусора и смогла только освободить очень мало места в куче.

Согласно документам Java, по умолчанию JVM настроена на выдачу этой ошибки, если процесс Java тратит более 98% своего времени, выполняя G C, и только в случае восстановления менее 2% кучи в каждый пробег. Другими словами, это означает, что наше приложение исчерпало почти всю доступную память, а сборщик мусора потратил слишком много времени, пытаясь очистить его, и несколько раз отказывал

Решение:

  • Увеличьте размер кучи, например -Xmx1g.
  • проверку предела можно отключить, добавив параметр -XX: -UseGCOverheadLimit в командную строку

Вы можете установить jvm Конфигурация env в tomcat / bin / setenv. sh Файл выглядит так:

CATALINA_OPTS="-Djava.awt.headless=true -Xms2048m -Xmx2048m  -XX:-UseGCOverheadLimit"
0 голосов
/ 03 мая 2020

Это может произойти, когда накладные расходы G C настолько велики, что приложение тратит почти все время на домашнюю деятельность G C (98%) . Тем самым нормальное функционирование приложения нарушается, и оно перестает отвечать на запросы. Вместо того, чтобы продолжать это, JVM издает это предупреждение об ошибке, которое необходимо учитывать.

Обычно происходит, когда:

  1. Размер кучи был ограничен для объектов, созданных как при обычной обработке приложения
  2. Произошла утечка памяти (кажется, что ее нет согласно VisualVM)

Я видел G C тратить циклы и почти весь процессор, когда совокупный размер объектов и других данных превышает около 80% кучи памяти. Это привело к G C, и это не могло вернуть много, приводя к другому G C и так далее.

Короче говоря, если вы уверены, что утечки памяти нет, первое, что вы должны попробовать:

  1. Увеличить размер кучи.

А также попытайтесь выяснить объекты, которые создаются приложением при запуске варианта использования. Вы можете уменьшить это число? Я помню, что одним из вариантов использования было чтение файла JSON. Вместо того, чтобы читать файл и создавать миллионы JSON объектов в куче, можно выполнить потоковую передачу файла (как во входных потоках) и прочитать его, создать объект, обработать его (и удалить после вычисления) и перейти к следующему .

Вы можете указать другой алгоритм G C (как указано в другом месте), но это не решит проблему в этом случае. Похоже, что проблема заключается в том, что приложение и OOM не отвечают, а не просто из-за более высокой задержки ответов приложения. Надеюсь, это поможет.

...