Voglio sapere qual è l'importanza del multithreading nelle applicazioni di rete? Ho fatto ricerche per un po 'ma non ho trovato riferimenti relativi a questo argomento specifico.
Voglio sapere qual è l'importanza del multithreading nelle applicazioni di rete? Ho fatto ricerche per un po 'ma non ho trovato riferimenti relativi a questo argomento specifico.
Il multithreading significa (apparentemente) fare molte cose contemporaneamente. Tecnicamente, non esiste una particolare connessione di threading con la rete; sono due metodi non correlati che a volte sono appropriati e talvolta no.
Tuttavia, quando esegui un server che può ricevere richieste da qualsiasi fonte sulla rete, in particolare da qualsiasi sorgente dell'intero Internet , diventa molto probabile che diverse richieste arriveranno contemporaneamente - o almeno più veloce di quanto tu possa servire al primo. Se non si desidera che il servizio rallenti molto rapidamente, una soluzione comune è mantenere un pool di thread e servire fino a N richieste pseudo-simultaneamente, in modo che il tempo di risposta non risenta di sovraccarico (almeno fino a quando non tutto i fili sono usati).
Quindi l'importanza del multi-threading per le applicazioni di rete è semplicemente che un modello comune di scrittura di software di rete (server) presenta un ovvio problema per cui i thread sono una soluzione ovvia.
In genere le persone si aspettano che un server sia in grado di gestire più client simultanei, da una manciata a decine di migliaia.
Ci sono diversi approcci per gestirlo. Ognuno con pro e contro.
Il processo del server principale monitora solo i socket di ascolto, quando accetta una connessione si stacca da un nuovo processo per gestirlo. L'istanza biforcuta del processo server può gestire la connessione stessa oppure può utilizzare exec per avviare un nuovo programma per gestire la connessione client. Quando il client si disconnette, termina il processo secondario.
Questo fornisce un alto livello di isolamento tra i client. Questo può o non può essere desiderabile. Ha un sovraccarico relativamente elevato quando un nuovo client si connette e anche un sovraccarico relativamente alto per client connessi simultaneamente.
Un'ulteriore complicazione con gli approcci basati su fork è la portabilità. Non tutti i sistemi operativi hanno il concetto di "forking".
Questo utilizza anche più processi, ma i processi figli sono mantenuti intorno riducendo il sovraccarico di biforcarne di nuovi. Tutti i processi client inattivi monitorano i socket di ascolto per le nuove connessioni. Quando una connessione viene accettata, il processo figlio si dedica a gestire tale connessione fino al completamento della connessione, quindi restituisce sé stesso al pool di figli inattivi.
L'isolamento del client è buono ma non buono come con fork on connect poiché lo stato di un processo figlio potrebbe essere stato influenzato dai client precedenti, ma è meglio che con approcci che gestiscono più client in un unico processo.
Simile al fork su connect ma invece di creare un fork viene creato un thread. Questo ha un overhead inferiore e facilita la condivisione dei dati tra i client. Al ribasso c'è un livello di isolamento molto più basso, un bug su un thread del client può facilmente bloccare l'intero processo del server e bisogna fare molta attenzione al blocco dei dati condivisi tra i thread.
Simile al prefork ma utilizzando thread anziché processi figlio. Salva l'overhead della creazione di un nuovo thread quando ogni client si connette ma aggiunge ulteriore complessità.
Il programma contiene un "motore di eventi", questo monitora tutti i socket, sia gli zoccoli di ascolto che i socket connessi. Quindi chiama i gestori di eventi quando il resto dell'applicazione deve fare qualcosa, ad esempio quando ci sono dati da leggere o quando è il momento di scrivere più dati.
L'aspetto positivo di questo approccio è che il sovraccarico dei thread è evitato. Anche i problemi relativi alla sicurezza del filo sono evitati.
Tuttavia ciò significa che il codice dell'applicazione deve essere strutturato come una serie di gestori di eventi. Le macchine a stati espliciti devono essere create per tracciare lo stato di una connessione piuttosto che essere gestite in modo naturale dal flusso del programma.
Un altro svantaggio è che è difficile evitare di inserire elementi di blocco nei gestori di eventi. Ad esempio sulla maggior parte dei sistemi operativi il file IO sta bloccando. Così è l'API standard per la traduzione tra hostname e indirizzi IP. Questo può facilmente uccidere le prestazioni.
E infine un processo guidato esclusivamente da un evento non può tenere conto di più processori.
È possibile combinare approcci con thread e eventi. Un approccio è che quando una connessione si trova in una fase "interessante" ottiene un thread dedicato, una volta che solo attività relativamente semplici come l'invio di dati in blocco restano trasferite in un thread che gestisce più connessioni.
Un altro approccio consiste nell'avere più thread indipendenti del motore degli eventi che gestiscono ciascuno un sottoinsieme di connessioni.
Questo può migliorare le prestazioni rispetto a un approccio a thread singolo per socket ma al costo di una complessità aggiuntiva.
Allo stesso modo è possibile combinare più processi con più thread. Questo può ridurre il danno quando un thread si blocca e riduce i problemi con l'esaurimento dello spazio degli indirizzi, evitando al tempo stesso il sovraccarico di molti processi.
Questo è sufficiente per i server, per quanto riguarda i client?
Un semplice client a riga di comando che si connette a un singolo server alla volta non ha bisogno di approcci multi-threading o event driven. Tuttavia non tutti i client sono così semplici.
Un client che vuole parlare con più server contemporaneamente ha molte delle stesse considerazioni che un server ha e sarà probabilmente necessario un approccio threaded o event-driven per gestirlo.
Allo stesso modo per un client della GUI le persone si aspettano che la GUI continui a funzionare mentre il client parla al server. Quindi è necessario un motore di eventi compatibile con il sistema di eventi GUI oppure è necessario un thread separato per il networking.
Leggi altre domande sui tag networking