Cosa succede se inizio troppi lavori in background?


13

Ho bisogno di fare un po 'di lavoro su 700 dispositivi di rete usando uno script prevede. Posso farlo in sequenza, ma finora l'autonomia è di circa 24 ore. Ciò è dovuto principalmente al tempo impiegato per stabilire una connessione e al ritardo nell'uscita da questi dispositivi (quelli vecchi). Sono in grado di stabilire due connessioni e farle funzionare in parallelo bene, ma fino a che punto posso spingerlo?

Non immagino di poterli fare tutti e 700 contemporaneamente, sicuramente c'è qualche limite al no. delle connessioni Telnet gestite dalla mia VM.

Se avessi provato a avviarne 700 in una sorta di loop come questo:

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

Con

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

  • Memoria 47,94 GB

La mia domanda è:

  1. Tutte le 700 istanze potrebbero essere eseguite contemporaneamente?
  2. Quanto lontano potrei arrivare fino a quando il mio server non raggiunge il limite?
  3. Quando viene raggiunto quel limite, aspetterà solo di iniziare la prossima iterazione fooo la scatola andrà in crash?

Purtroppo sto correndo in un ambiente di produzione aziendale, quindi non posso proprio provare a vedere cosa succede.


3
Ho avuto fortuna con parallel, usando circa 50 lavori simultanei. È un ottimo mezzo tra il parallelismo di 1 e 700. L'altra cosa bella è che è senza batch. Una singola connessione bloccata si bloccherà solo se stessa, non nessuna delle altre. Il principale svantaggio è la gestione degli errori. Nessuno di questi approcci basati su shell gestirà con grazia errori. Dovrai controllare manualmente il successo da solo e fare i tuoi tentativi.
Adam,

1
La coda delle attività potrebbe essere 700 oggi, ma la dimensione può espandersi? Controlla che lo spazio di swap cresca, ovvero che hai raggiunto il limite di memoria. E cpu% non è una buona misura (per linux / unix), meglio considerare la media del carico (lunghezza della coda di esecuzione).
ChuckCottrill,

1
Il modo più recente in cui ho interrotto la produzione nel mio nuovo tipo di lavoro è stato quello di eseguire accidentalmente contemporaneamente oltre un milione di lavori in background di breve durata. Hanno coinvolto JVM (wait wait put down the pitchforks), quindi le conseguenze erano "limitate" a centinaia di migliaia di file di segnalazione errori che i thread non potevano essere avviati.
michaelb958 - GoFundMonica


1
@KuboMD E finché nessun altro vuole mai usare il tuo codice.
l0b0

Risposte:


17

Tutte le 700 istanze potrebbero essere eseguite contemporaneamente?

Dipende da cosa intendi contemporaneamente. Se siamo pignoli, allora no, non possono farlo a meno che tu non abbia 700 thread di esecuzione sul tuo sistema che puoi utilizzare (quindi probabilmente no). Realisticamente, sì, probabilmente lo possono, a condizione che tu abbia abbastanza RAM e / o spazio di swap sul sistema. UNIX ed i suoi vari figli sono straordinariamente bravi a gestire enormi livelli di concorrenza, questo è uno dei motivi per cui sono così popolari per l'uso su larga scala dell'HPC.

Quanto lontano potrei arrivare fino a quando il mio server non raggiunge il limite?

È impossibile rispondere concretamente senza molte più informazioni. Praticamente, è necessario disporre di memoria sufficiente per soddisfare:

  • L'intero fabbisogno di memoria di runtime di un lavoro, per 700.
  • I requisiti di memoria di bash per gestire molti lavori (bash non è orribile al riguardo, ma il controllo dei lavori non è esattamente efficiente in termini di memoria).
  • Eventuali altri requisiti di memoria sul sistema.

Supponendo che lo soddisfi (di nuovo, con solo 50 GB di RAM, devi ancora affrontare altri problemi:

  • Quanto tempo della CPU sarà sprecato da bash sul controllo del lavoro? Probabilmente non molto, ma con centinaia di posti di lavoro, potrebbe essere significativo.
  • Di quanta larghezza di banda di rete avrà bisogno? L'apertura di tutte queste connessioni potrebbe inondare la rete per un paio di minuti a seconda della larghezza di banda e della latenza.
  • Molte altre cose a cui probabilmente non ho pensato.

Quando viene raggiunto quel limite, aspetterà solo di iniziare la prossima iterazione al largo o la scatola andrà in crash?

Dipende da quale limite viene raggiunto. Se è memoria, qualcosa morirà sul sistema (in particolare, verrà ucciso dal kernel nel tentativo di liberare memoria) o il sistema stesso potrebbe arrestarsi in modo anomalo (non è insolito configurare i sistemi affinché si arrestino intenzionalmente quando si esaurisce la memoria). Se è il tempo della CPU, continuerà senza problemi, sarà impossibile fare molto altro sul sistema. Se si tratta della rete, è possibile che si verifichino arresti anomali di altri sistemi o servizi.


Ciò di cui hai davvero bisogno qui non è eseguire tutti i lavori contemporaneamente. Invece, dividerli in batch ed eseguire tutti i lavori all'interno di un batch contemporaneamente, lasciarli finire, quindi avviare il batch successivo. GNU Parallel ( https://www.gnu.org/software/parallel/ ) può essere usato per questo, ma è meno che ideale a quella scala in un ambiente di produzione (se ci vai, non diventare troppo aggressivo, come ho detto, potresti inondare la rete e influire su sistemi che altrimenti non toccheresti). Consiglio vivamente di esaminare uno strumento di orchestrazione di rete adeguato come Ansible ( https://www.ansible.com/), poiché ciò non solo risolverà i tuoi problemi di concorrenza (Ansible esegue il batch come ho già menzionato automaticamente), ma ti fornirà anche molte altre utili funzionalità con cui lavorare (come l'esecuzione idempotente di attività, bei report di stato e integrazione nativa con un gran numero di altri strumenti).


Esistono modi per eseguire un numero limitato di attività in background (usando bash, perl, python, et al), monitorare il completamento delle attività ed eseguire più attività al completamento delle attività precedenti. Un approccio semplice sarebbe quello di raccogliere batch di attività rappresentate da file in sottodirectory ed elaborare un batch alla volta. Ci sono altri modi ...
ChuckCottrill,

Questo include anche sistemi unix-like? E cos'è "GUN parallel"?
Biswapriyo,

2
@ChuckCottrill Sì, ci sono davvero altri modi per farlo. Data la mia esperienza personale con questo tipo di cose, è quasi sempre meglio ottenere un vero strumento di orchestrazione piuttosto che provare a implementare la propria soluzione, soprattutto dopo aver superato alcune dozzine di sistemi in termini di scala.
Austin Hemmelgarn,


3
@forest Sì, è possibile utilizzare i rlimits per impedire il crash del sistema, ma risolverli in un caso come questo non è facile (è necessario conoscere in anticipo quali sono i requisiti di risorse per le attività) e non proteggere il il resto della rete da qualsiasi impatto che questi lavori possono causare (il che è probabilmente un problema potenzialmente molto più grande del crash del sistema locale).
Austin Hemmelgarn,

12

È difficile dire in modo specifico quante istanze potrebbero essere eseguite come processi in background nel modo descritto. Ma un server normale può certamente mantenere 700 connessioni simultanee purché lo si faccia correttamente. I server web lo fanno sempre.

Posso suggerire di usare GNU parallel ( https://www.gnu.org/software/parallel/ ) o qualcosa di simile per ottenere questo risultato? Ti darebbe una serie di vantaggi all'approccio del lavoro in background:

  • È possibile modificare facilmente il numero di sessioni simultanee.
  • E attenderà il completamento delle sessioni prima di avviarne di nuove.
  • È più facile interrompere.

Dai un'occhiata qui per un rapido avvio: https://www.gnu.org/software/parallel/parallel_tutorial.html#A-single-input-source


1
Interessante! Darò un'occhiata a questo Sai se tentare questo tipo di operazione (senza l'aiuto di Parallel) rischierebbe di arrestare l'hypervisor?
KuboMD,

2
@KuboMD se riesci a bloccare l'hypervisor con qualcosa di così banale, è un bug
nell'hypervisor

a parte questo, i server web usano spesso threading o elaborazione basata su eventi (esempio: gunicorn.org )
ChuckCottrill

10

L'uso &per l'elaborazione parallela va bene quando ne fai alcuni e quando controlli i progressi. Ma se lavori in un ambiente di produzione aziendale hai bisogno di qualcosa che ti dia un migliore controllo.

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

Questo verrà eseguito fooper ogni file in ~/sagLogs. Avvia un lavoro ogni 0,5 secondi, eseguirà il maggior numero possibile di lavori in parallelo fino a quando 1 GB di RAM è libero, ma rispetterà i limiti del sistema (ad es. Numero di file e processi). In genere questo significa che eseguirai 250 lavori in parallelo se non hai modificato il numero di file aperti consentiti. Se si regola il numero di file aperti, non si dovrebbe avere problemi a eseguire 32000 in parallelo, purché si disponga di memoria sufficiente.

Se un lavoro ha esito negativo (ad es. Restituisce un codice di errore) verrà riprovato 10 volte.

my.log ti dirà se un lavoro ha esito positivo (dopo eventualmente tentativi) o meno.


Sembra molto promettente, grazie.
KuboMD

Ho fatto un semplice test cat ~/sagLogs/* >> ~/woah | parallele Holy Moly che è stato veloce. 1.054.552 linee in un batter d'occhio.
KuboMD,

3
Il comando che hai dato ha un doppio reindirizzamento, quindi non credo che faccia quello che intendi fare. GNU Parallel ha un sovraccarico di 10 ms per lavoro, quindi i lavori 1M dovrebbero richiedere nell'ordine di 3 ore.
Ole Tange,

1
Non è affatto applicabile se tutto ciò che si desidera fare è semplicemente concatenare i file.
Ole Tange,

1
@KuboMD un banale loop occupato della CPU come awk 'BEGIN{for(i=rand()*10000000; i<100000000;i++){}}' avrebbe funzionato per giocare con. Oppure provalo su un'attività come sleep 10vederlo mantenere i nlavori in volo senza impiegare molto tempo della CPU. ad es. time parallel sleep ::: {100..1}per eseguire sleep da 100 a 1 secondo.
Peter Cordes,

1

Cosa succede se inizio troppi lavori in background?

il sistema diventerà lento e non risponderà, il caso peggiore è così non rispondente che sarebbe meglio semplicemente premere il pulsante di accensione e fare un riavvio difficile ... questo sarebbe eseguire qualcosa come root dove avrebbe avuto il privilegio di cavarsela. Se lo script bash è in esecuzione con privilegi di utente normale, quindi la prima cosa che viene in mente è /etc/security/limits.confe /etc/systemd/system.confe tutte le variabili in essa a [idealmente parlando] prevenire utente (s) dal sovraccarico del sistema.

  • cpu = xeon E5649, ovvero una cpu a 12 core ; quindi hai 12 core per 12 processi da eseguire contemporaneamente utilizzando ciascuno dei dodici core al 100%. Se avvii 24 processi, ognuno funzionerebbe al 50% di utilizzo su ciascuno dei dodici core, 700 processi = 1,7% ma è un computer fintanto che tutto si completa correttamente in un periodo di tempo accettabile, quindi = successo; essere efficienti non è sempre rilevante.

    1. Tutte le 700 istanze potrebbero essere eseguite contemporaneamente? Certamente, 700 non è un numero elevato; Il mio /etc/security/limits.conf maxprocpredefinito è 4.135.275 per esempio

    2. Quanto lontano potrei arrivare fino a quando il mio server non raggiunge il limite? Molto più di 700 ne sono sicuro.

    3. Limiti ... cosa accadrà se lo script viene avviato con un account utente [e generalmente anche il root si limits.confapplica praticamente a tutti] è che lo script uscirà dopo aver provato a fare foo &700 volte; ti aspetteresti di vedere 700 processi foo ciascuno con un pid diverso ma potresti vedere solo 456 (scelta del numero casuale) e l'altro 244 non è mai stato avviato perché sono stati bloccati da un limite di sicurezza o di limite di sistema.

Milione di dollari di domanda: quanti ne dovresti eseguire contemporaneamente?

essere coinvolto con la rete e hai detto che ciascuno farà una connessione telnet, immaginando che ti imbatterai in limiti di rete e sovraccarico prima di farlo per limiti cpu e ram. Ma non so cosa stai facendo nello specifico, ciò che probabilmente accadrà è che puoi dare il via a tutti i 700 contemporaneamente, ma le cose si bloccheranno automaticamente fino a quando i processi precedenti e le connessioni di rete non finiranno e si chiuderanno in base a vari limiti di sistema, o qualcosa di simile al i primi 500 inizieranno, mentre i restanti 200 no perché i limiti del sistema o del kernel lo impediscono. Ma per quanto molti corrano contemporaneamente, ce ne saranno alcuni dolcissimiposto per fare le cose il più velocemente possibile ... minimizzando le spese generali e aumentando l'efficienza. Essendo 12 core (o 24 se si hanno 2 CPU), iniziare con 12 (o 24) contemporaneamente e quindi aumentare quel numero di lotto simultaneo di 12 o 24 fino a quando non si vede un miglioramento del tempo di esecuzione.

suggerimento: google max connessioni telnet e guarda come questo si applica ai tuoi sistemi. Inoltre, non dimenticare i firewall. Effettua anche un rapido calcolo della memoria necessaria per processo x 700; assicurati che <RAM disponibile (circa 50 GB nel tuo caso), altrimenti il ​​sistema inizierà a utilizzare SWAP e sostanzialmente non risponderà. Quindi avvia 12, 24, N processi alla volta e monitora la RAM libera, quindi aumenta N già avendo una certa conoscenza di ciò che sta accadendo.

Per impostazione predefinita, RHEL limita il numero di connessioni telnet da un singolo host a 10 sessioni simultanee. Questa è una funzione di sicurezza ... impostata su 10, /etc/xinetd.conf, cambia il valore “per_source”.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.