Живая блокировка на сокете Linux UNIX, что делать?

Мы работаем с приложением Linux, которое разветвляет большое количество (более 1000) дочерних процессов. Эти дочерние процессы взаимодействуют с главным процессом через сокет дейтаграммы UNIX (один общий для всех дочерних процессов). Сокет дейтаграмм UNIX используется помимо других коммуникаций также для регистрации. Вся система работает нормально, пока приложение не отреагирует на массивную внешнюю ошибку - скажем, сбой базы данных приложения. Мы заметили, что в такой ситуации дочерние процессы начинают генерировать огромное количество событий журнала ошибок, что, вероятно, правильно, так как каждый дочерний процесс подвержен этой аварии. Через несколько минут нагрузка возрастает выше 8000 при потреблении ЦП системой (не пользователем!) На 80-100%. Состояние может быть восстановлено только в том случае, если приложение убито или чаще, коробка становится непригодной для использования из-за медленных ответов и должна быть перезагружена.

Исследование дампов ядра показывает, что дочерние процессы заблокированы в send() системный вызов на сокете UNIX, говорящий с основным процессом. Сокет UNIX настроен как неблокирующий, и приложение реализует правильную обработку EAGAIN, Более глубокий анализ показывает, что в ядре существует условие блокировки в реальном времени. Очевидно, что процессы конкурируют за доступ к некоторому ресурсу, связанному с сокетом UNIX.

Вопросы: Вы когда-нибудь встречали это или подобное поведение раньше? Мы что-то упускаем из-за параллелизма сокетов UNIX?

Версии:
- CentOS Linux выпуск 7.3.1611 (Core).
- Ядро Linux 3.10.0-514.16.1.el7.x86_64 x86_64.

1 ответ

Здесь явно есть место для улучшения со стороны ядра, и есть вероятность, что это довольно низко висящий фрукт. Я не собираюсь спекулировать. Скорее всего, проблема будет легко заметна с помощью флеймографов.

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

Вместо этого, когда происходит серьезное событие, просто зарегистрируйте его один раз, а затем снова зарегистрируйте, что оно очищено (например, обратите внимание, что соединение с базой данных прервано, обратите внимание, когда оно восстановлено, но не регистрируйте каждый запрос, что он мертв), В качестве альтернативы вы можете регистрировать это периодически или с помощью limitlimit. В любом случае, просто рассылка спама - это неправильно.

Огромное количество детей (1000+?) Кажется чрезмерным и ставит под вопрос обоснованность дизайна этого проекта. Можете ли вы рассказать, что там происходит?

Другие вопросы по тегам