Que se passe-t-il si je commence trop d'emplois d'arrière-plan?

13

J'ai besoin de travailler sur 700 périphériques réseau à l'aide d'un script expect. Je peux le faire séquentiellement, mais jusqu'à présent, le temps d'exécution est d'environ 24 heures. Cela est principalement dû au temps nécessaire pour établir une connexion et au retard dans la sortie de ces appareils (anciens). Je peux établir deux connexions et les faire fonctionner en parallèle très bien, mais jusqu'où puis-je pousser cela?

Je n'imagine pas que je pourrais faire les 700 à la fois, il y a sûrement une certaine limite au non. de connexions telnet que ma machine virtuelle peut gérer.

Si j'essayais d'en démarrer 700 dans une sorte de boucle comme celle-ci:

for node in `ls ~/sagLogs/`; do  
    foo &  
done

Avec

  • CPU 12 CPU x Intel (R) Xeon (R) CPU E5649 à 2,53 GHz

  • Mémoire 47,94 Go

Ma question est:

  1. Les 700 instances pourraient-elles éventuellement s'exécuter simultanément?
  2. Jusqu'où pourrais-je aller jusqu'à ce que mon serveur atteigne sa limite?
  3. Une fois cette limite atteinte, attendra-t-il simplement de commencer la prochaine itération fooou la boîte se bloquera-t-elle?

Je cours malheureusement dans un environnement de production d'entreprise, donc je ne peux pas exactement essayer de voir ce qui se passe.

KuboMD
la source
3
J'ai eu de la chance en parallelutilisant environ 50 emplois simultanés. C'est un excellent moyen entre le parallélisme de 1 et 700. L'autre chose intéressante est que c'est sans lot. Une seule connexion bloquée ne se bloquera que sur elle-même, pas sur les autres. Le principal inconvénient est la gestion des erreurs. Aucune de ces approches basées sur le shell ne gèrera correctement les erreurs. Vous devrez vérifier manuellement le succès vous-même et faire vos propres tentatives.
Adam
1
Votre file d'attente de tâches peut être de 700 aujourd'hui, mais la taille peut-elle augmenter? Faites attention à l'espace de swap pour augmenter - c'est une indication que vous avez atteint la limite de mémoire. Et cpu% n'est pas une bonne mesure (pour linux / unix), mieux vaut considérer la charge moyenne (longueur de la file d'attente d'exécution).
ChuckCottrill
1
La façon la plus récente dont j'ai interrompu la production à mon travail encore un peu nouveau était en exécutant accidentellement un million d'emplois de plus de courte durée en même temps. Ils impliquaient des machines virtuelles Java (attendez, posez les fourches), de sorte que les conséquences étaient `` limitées '' à des centaines de milliers de fichiers de rapport d'erreur que les threads ne pouvaient pas démarrer.
michaelb958 - GoFundMonica
4
Nitpick: Ne pas analyser la lssortie
l0b0
1
@KuboMD Et tant que personne d'autre ne veut utiliser votre code.
l0b0

Réponses:

17

Les 700 instances pourraient-elles éventuellement s'exécuter simultanément?

Cela dépend de ce que vous entendez par simultanément. Si nous sommes pointilleux, alors non, ils ne peuvent pas sauf si vous avez 700 threads d'exécution sur votre système que vous pouvez utiliser (donc probablement pas). De manière réaliste, oui, ils le peuvent probablement, à condition que vous ayez suffisamment de RAM et / ou d'espace d'échange sur le système. UNIX et ses divers enfants sont remarquablement bons pour gérer d'énormes niveaux de simultanéité, c'est en partie pourquoi ils sont si populaires pour une utilisation HPC à grande échelle.

Jusqu'où pourrais-je aller jusqu'à ce que mon serveur atteigne sa limite?

Il est impossible de répondre concrètement sans beaucoup plus d'informations. À peu près, vous devez avoir suffisamment de mémoire pour répondre:

  • La totalité de la mémoire requise pour l'exécution d'un travail, 700 fois.
  • Les besoins en mémoire de bash pour gérer autant de tâches (bash n'est pas horrible à ce sujet, mais le contrôle des tâches n'est pas exactement efficace en mémoire).
  • Tout autre besoin de mémoire sur le système.

En supposant que vous rencontriez cela (encore une fois, avec seulement 50 Go de RAM, vous devez toujours faire face à d'autres problèmes:

  • Combien de temps CPU va être perdu par bash sur le contrôle des tâches? Probablement pas beaucoup, mais avec des centaines d'emplois, cela pourrait être important.
  • De quelle bande passante réseau aura-t-elle besoin? L'ouverture de toutes ces connexions peut submerger votre réseau pendant quelques minutes en fonction de votre bande passante et de votre latence.
  • Beaucoup d'autres choses auxquelles je n'ai probablement pas pensé.

Lorsque cette limite est atteinte, attendra-t-il simplement de commencer la prochaine itération hors de foo ou la boîte plantera-t-elle?

Cela dépend de la limite atteinte. S'il s'agit de mémoire, quelque chose va mourir sur le système (plus précisément, être tué par le noyau dans une tentative de libérer de la mémoire) ou le système lui-même peut se bloquer (il n'est pas rare de configurer des systèmes pour qu'ils se bloquent intentionnellement en cas de manque de mémoire). Si c'est le temps CPU, cela continuera sans problème, il sera tout simplement impossible de faire beaucoup d'autres choses sur le système. Si c'est le réseau, vous risquez de planter d' autres systèmes ou services.


Ce dont vous avez vraiment besoin ici, ce n'est pas d'exécuter tous les travaux en même temps. Au lieu de cela, divisez-les en lots et exécutez tous les travaux d'un lot en même temps, laissez-les terminer, puis démarrez le lot suivant. GNU Parallel ( https://www.gnu.org/software/parallel/ ) peut être utilisé pour cela, mais c'est loin d'être idéal à cette échelle dans un environnement de production (si vous y allez, ne soyez pas trop agressif, comme je l'ai dit, vous pourriez submerger le réseau et affecter des systèmes que vous ne toucheriez pas autrement). Je recommanderais vraiment de rechercher un outil d'orchestration réseau approprié comme Ansible ( https://www.ansible.com/), car cela résoudra non seulement vos problèmes de concurrence (Ansible effectue automatiquement le traitement par lots comme je l'ai mentionné ci-dessus), mais vous offre également de nombreuses autres fonctionnalités utiles (comme l'exécution idempotente des tâches, de beaux rapports d'état et l'intégration native avec un très grand nombre d’autres outils).

Austin Hemmelgarn
la source
Il existe des moyens d'exécuter un nombre limité de tâches en arrière-plan (à l'aide de bash, perl, python, etc.), de surveiller la fin des tâches et d'exécuter plus de tâches à mesure que les tâches précédentes sont terminées. Une approche simple serait de collecter des lots de tâches représentées par des fichiers dans des sous-répertoires et de traiter un lot à la fois. Il y a d'autres façons ...
ChuckCottrill
Cela inclut-il également les systèmes de type Unix? Et qu'est-ce que "GUN parallel"?
Biswapriyo
2
@ChuckCottrill Oui, il existe en effet d'autres façons de procéder. Compte tenu de ma propre expérience dans ce type de chose, il est presque toujours préférable de simplement obtenir un véritable outil d'orchestration que d'essayer de lancer votre propre solution, surtout une fois que vous avez dépassé quelques dizaines de systèmes en termes d'échelle.
Austin Hemmelgarn
3
@forest Oui, vous pouvez utiliser rlimits pour empêcher le système de tomber en panne, mais les corriger dans un cas comme celui-ci n'est pas facile (vous avez en quelque sorte besoin de savoir quelles sont les ressources nécessaires pour les tâches à l'avance) et ne protège pas le reste du réseau de tout impact que ces travaux peuvent causer (ce qui est sans doute un problème potentiellement beaucoup plus important que de planter le système local).
Austin Hemmelgarn
12

Il est difficile de dire précisément combien d'instances pourraient être exécutées en tant que tâches d'arrière-plan de la manière que vous décrivez. Mais un serveur normal peut certainement maintenir 700 connexions simultanées tant que vous le faites correctement. Les serveurs Web font cela tout le temps.

Puis-je vous suggérer d'utiliser parallèle GNU ( https://www.gnu.org/software/parallel/ ) ou quelque chose de similaire pour accomplir cela? Cela vous donnerait un certain nombre d'avantages à l'approche de travail de fond:

  • Vous pouvez facilement modifier le nombre de sessions simultanées.
  • Et il attendra la fin des sessions avant d'en commencer de nouvelles.
  • Il est plus facile d'avorter.

Jetez un œil ici pour un démarrage rapide: https://www.gnu.org/software/parallel/parallel_tutorial.html#A-single-input-source

laenkeio
la source
1
Intéressant! Je vais regarder ça. Savez-vous si tenter ce type d'opération (sans l'aide de Parallel) risquerait de planter l'hyperviseur?
KuboMD
2
@KuboMD si vous pouvez planter l'hyperviseur avec quelque chose de si banal, c'est un bogue dans l'hyperviseur :)
hobbs
en passant, les serveurs Web utilisent souvent le threading ou le traitement basé sur les événements (exemple: gunicorn.org )
ChuckCottrill
10

L'utilisation &pour le traitement parallèle est correcte lorsque vous en effectuez quelques-unes et lorsque vous surveillez les progrès. Mais si vous travaillez dans un environnement de production d'entreprise, vous avez besoin de quelque chose qui vous donne un meilleur contrôle.

ls ~/sagLogs/ | parallel --delay 0.5 --memfree 1G -j0 --joblog my.log --retries 10 foo {}

Cela s'exécutera foopour chaque fichier dans ~/sagLogs. Il démarre un travail toutes les 0,5 secondes, il exécutera autant de travaux en parallèle que possible tant que 1 Go de RAM est libre, mais respectera les limites de votre système (par exemple, le nombre de fichiers et de processus). Cela signifie généralement que vous exécuterez 250 travaux en parallèle si vous n'avez pas ajusté le nombre de fichiers ouverts autorisés. Si vous ajustez le nombre de fichiers ouverts, vous ne devriez avoir aucun problème à exécuter 32000 en parallèle - tant que vous avez suffisamment de mémoire.

Si un travail échoue (c'est-à-dire revient avec un code d'erreur), il sera réessayé 10 fois.

my.log vous dira si un travail réussit (après de nouvelles tentatives éventuelles) ou non.

Ole Tange
la source
Cela semble très prometteur, merci.
KuboMD
Ran un test simple faisant cat ~/sagLogs/* >> ~/woah | parallelet saint moly qui était rapide. 1 054 552 lignes en un clin d'œil.
KuboMD
3
La commande que vous avez donnée a une double redirection, donc je ne pense pas qu'elle fait ce que vous avez l'intention de faire. GNU Parallel a une surcharge de 10 ms par tâche, donc 1 million de tâches devraient prendre de l'ordre de 3 heures.
Ole Tange
1
Cela ne s'applique pas du tout si tout ce que vous voulez faire est simplement de concaténer les fichiers.
Ole Tange
1
@KuboMD une boucle de CPU insignifiante comme awk 'BEGIN{for(i=rand()*10000000; i<100000000;i++){}}' pourrait fonctionner pour jouer avec. Ou essayez-le sur une tâche comme sleep 10pour le voir garder les ntravaux en cours sans utiliser beaucoup de temps CPU. Par exemple, time parallel sleep ::: {100..1}pour exécuter les périodes de sommeil de 100 à 1 seconde.
Peter Cordes
1

Que se passe-t-il si je commence trop d'emplois d'arrière-plan?

le système deviendra lent et ne répondra pas, le pire des cas est si insensible qu'il serait préférable d'appuyer simplement sur le bouton d'alimentation et de faire un redémarrage dur ... ce serait exécuter quelque chose en tant que root où il aurait le privilège de s'en tirer. Si votre script bash est en cours d' exécution sous les privilèges utilisateurs réguliers, la première chose qui vient à l' esprit est /etc/security/limits.confet /etc/systemd/system.confet toutes les variables qui y sont à [idéalement parlant] empêcher l' utilisateur (s) de la surcharge du système.

  • cpu = xeon E5649, c'est-à-dire un cpu à 12 cœurs ; vous disposez donc de 12 cœurs pour 12 processus à exécuter simultanément, chacun utilisant l'un des douze cœurs à 100%. Si vous lancez 24 processus, chacun fonctionnerait à 50% d'utilisation sur chacun des douze cœurs, 700 processus = 1,7% mais c'est un ordinateur tant que tout se déroule correctement dans un délai correct, alors que = succès; être efficace n'est pas toujours pertinent.

    1. Les 700 instances pourraient-elles éventuellement s'exécuter simultanément? Certes, 700 n'est pas un grand nombre; ma /etc/security/limits.conf maxprocpar défaut est 4 135 275 par exemple

    2. Jusqu'où pourrais-je aller jusqu'à ce que mon serveur atteigne sa limite? Bien plus que 700 je suis sûr.

    3. Limites ... ce qui se passera si le script est lancé sous un compte utilisateur [et généralement root aussi limits.confs'applique à peu près à tout le monde], c'est que le script se terminera juste après avoir essayé de le faire foo &700 fois; vous vous attendriez à voir alors 700 processus foo chacun avec un pid différent mais vous pourriez ne voir que 456 (choix de nombre aléatoire) et les autres 244 n'ont jamais démarré car ils ont été bloqués par une limite de sécurité ou systemd.

Million $ question: combien devez-vous exécuter simultanément?

être impliqué dans le réseau et vous avez dit que chacun fera une connexion telnet, vous devez savoir que vous rencontrerez des limites de réseau et des frais généraux avant de le faire pour les limites de processeur et de ram. Mais je ne sais pas ce que vous faites spécifiquement, ce qui se produira probablement, c'est que vous pouvez lancer les 700 à la fois, mais les choses se bloqueront automatiquement jusqu'à ce que les processus précédents et les connexions réseau se terminent et se ferment en fonction de diverses limites du système, ou quelque chose comme le les 500 premiers démarrent puis les 200 restants ne le seront pas car les limites du système ou du noyau l'empêchent. Mais mais beaucoup courir à la fois, il y aura quelques douceâtreendroit pour faire avancer les choses le plus rapidement possible ... minimiser les frais généraux et augmenter l'efficacité. Être 12 cœurs (ou 24 si vous avez 2 processeurs), commencez par 12 (ou 24) à la fois, puis augmentez ce numéro de lot simultané de 12 ou 24 jusqu'à ce que vous ne voyiez pas d'amélioration de la durée d'exécution.

astuce: google max telnet connections et voyez comment cela s'applique à vos systèmes. N'oubliez pas non plus les pare-feu. Faites également un calcul rapide de la mémoire nécessaire par processus x 700; assurez-vous que <RAM disponible (environ 50 Go dans votre cas) sinon le système commencera à utiliser SWAP et ne répondra plus. Alors lancez 12, 24, N processus à la fois et surveillez la RAM libre, puis augmentez N en ayant déjà une certaine connaissance de ce qui se passe.

Par défaut, RHEL limite le nombre de connexions Telnet d'un seul hôte à 10 sessions simultanées. Il s'agit d'une fonction de sécurité ... définie sur 10, /etc/xinetd.conf, changez la valeur "per_source".

Ron
la source