Nous exploitons une application Linux qui forge un grand nombre (plus de 1000) de processus enfants. Ces processus enfants communiquent avec le processus maître via le socket de datagramme UNIX (un partagé entre tous les processus enfants). Le socket de datagramme UNIX est utilisé en plus des autres communications pour la journalisation. L'ensemble du système fonctionne bien jusqu'à ce que l'application doit réagir à une erreur externe massive - disons un crash de la base de données d'application. Nous avons observé que dans une telle situation, les processus enfants commencent à générer une quantité énorme d'événements du journal des erreurs, ce qui est probablement correct puisque chaque enfant est impacté par ce crash. Après quelques minutes, la charge augmente au-dessus de 8000 avec 80-100% CPU système consommation (pas utilisateur!). L'état est récupérable uniquement si l'application est supprimée ou, plus communément, la boîte devient inutilisable en raison des réponses lentes et doit être redémarrée.Verrouillage en direct sur socket Linux UNIX, que faire?
L'examen des vidages de la mémoire principale montre que les processus enfants sont bloqués dans send()
syscall sur le socket UNIX, en parlant au processus maître. La socket UNIX est configurée comme non bloquante et l'application met en œuvre une gestion correcte de EAGAIN
. Une analyse plus approfondie indique qu'il existe une condition de verrouillage en direct dans le noyau. De toute évidence, les processus sont en concurrence pour l'accès à certaines ressources liées au socket UNIX. Questions: Avez-vous déjà rencontré ce comportement ou un comportement similaire auparavant? Manquons-nous quelque chose au sujet du parallélisme de socket UNIX?
Versions:
- Version CentOS Linux 7.3.1611 (principale).
- Kernel Linux 3.10.0-514.16.1.el7.x86_64 x86_64.
Je ne dirais pas qu'ils sont "bloqués" dans send(), mais qu'ils y passent la plupart de leur temps de traitement. Est-il possible que le tampon socket soit plein? Quoi qu'il en soit, penser à un bug dans le noyau serait le dernier recours pour moi. –
Le tampon de socket est le plus certainement plein mais il est normalement géré via le mécanisme EAGAIN b/c Le socket UNIX est non-bloquant. Je suis d'accord avec la partie bug du noyau. –
S'il n'y a pas de délai (par exemple de veille) entre les envois infructueux, c'est le résultat que vous obtiendrez. –