Java периодически зависает при futex и очень низком выходе IO

В настоящее время мое приложение периодически блокируется в IO, а выход очень низок. Я использую некоторую команду для отслеживания процесса.

Используя jstack, я обнаружил, что приложение висит на FileOutputStream.writeBytes.

Используя strace -f -c -p pid для сбора информации о syscall, я нашел это. Для нормальной ситуации он имеет как futex, так и write syscalls. Но когда это стало ненормальным, есть только системные вызовы futex. Приложение продолжает вызывать futex, но все не удалось и выбрасывает ETIMEDOUT, например:

<futex resumed>  =-1 ETIMEDOUT (Connecton timed out)
futex(Ox7f823, FUTEX_WAKE_PRIVATE,1)=0
futex(Ox7f824, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME) =-1<unfinished>
<futex resumed>  =-1 ETIMEDOUT (Connecton timed out)
futex(Ox7f823, FUTEX_WAKE_PRIVATE,1)=0
futex(Ox7f824, FUTEX_WAIT_BITSET_PRIVATE|FUTEX_CLOCK_REALTIME) =-1<unfinished>

Эта проблема происходит периодически и продолжается в течение времени или часа, и снова идет нормально.

Эскипично, когда блокируется в IO, echo 3 > /proc/sys/vm/drop_caches всегда заставляет его нормально работать. Я googled это и нашел некоторый подобный proleam, перечисление ниже.

  • прыжок второй. Не работает, наша система ntpd остановлена.
  • прозрачная ошибка огромной страницы. https://bugzilla.redhat.com/show_bug.cgi?id=879801 Это очень похоже на мой probleam, но мой процесс с высокой нагрузкой является нормальным, и нагрузка всегда равна нулю. Escipally drop_caches также работает для моего приложения. И моя система также многоядерная и большая память. Это не работает для меня. Итак, кто-нибудь встретил один и тот же пролемам или знаком с этой проблемой?

Некоторая информация о моей системе. ОС: Redhat 6.1, версия ядра 2.6.31

JDK: 1.7.0_05

CPU: X5650, 24cores

Память: 24 ГБ и 48 ГБ

Ответ 2

В дополнение к скачкам тактовой частоты и вышеупомянутой (довольно старой) ошибке в ядре THP, еще одной распространенной причиной неожиданного блокирования Java в IO является очень медленное чтение и блокировка /dev/random, что в некоторых библиотеках предпочтительнее, чем в более часто используемых и намного лучше выполняемых /dev/urandom.

Простой способ определить, был ли это виновник:

sudo mv /dev/random /dev/random.real
sudo ln -s /dev/urandom /dev/random

... затем перезапустите приложение и посмотрите, не остановит ли оно блокировку ввода-вывода. После завершения теста вы, вероятно, захотите восстановить /dev/random:

sudo mv /dev/random.real /dev/random

... и откройте ошибку с поставщиком приложений, который попросит использовать /dev/urandom, где это уместно.