2013-07-11 7 views
26

Dopo aver letto il famoso C10k article e aver cercato sul Web come sono evolute le cose da quando è stato scritto, vorrei sapere se sarebbe possibile per uno standard di oggi server per gestire > 10000 connessioni simultanee utilizzando un thread per connessione (eventualmente con l'aiuto di un pool di thread per evitare il processo di creazione/abbattimento).TCP/IP - Risoluzione del C10K con l'approccio thread per client


Alcuni dettagli che possono influenzare l'approccio al problema:

  1. input, elaborazione e output intermedio.
  2. Lunghezza di ciascuna connessione.
  3. Specifiche tecniche del server (nuclei, processori, RAM, ecc ...)
  4. Combinando questo sistema con tecniche alternative come l'AIO, polling, fili verdi, ecc ...

Ovviamente non sono un esperto in materia, quindi qualsiasi commento o consiglio sarà molto apprezzato :)

risposta

3

Gli approcci usuali per i server sono: (a) thread per connessione (spesso con un pool di thread) o (b) single threaded con IO asincrono (spesso con epoll o kqueue). Il mio pensiero è che alcuni elementi di questi approcci possono, e spesso dovrebbero, essere combinati per utilizzare l'IO asincrono (con epoll o kqueue) e quindi passare la richiesta di connessione a un pool di thread da elaborare. Questo approccio combinerebbe l'invio efficiente dell'IO asincrono con il parallelismo fornito dal pool di thread.

Ho scritto un tale server per divertimento (in C++) che usa epoll su Linux e kqueue su FreeBSD e OSX insieme a un pool di thread. Ho solo bisogno di eseguirlo per test intensivi, fare un po 'di pulizia del codice e poi lanciarlo su github (speriamo presto).

+2

Forse è che sono un po 'confuso, ma ho pensato che 'epoll' non fosse esattamente asincrono. Dopo alcune ricerche ho trovato diversi testi che dicevano che 'AIO' funzionava meglio in combinazione con un pool di thread, e' epoll' con un singolo thread: [Confronto tra aio ed epoll] (http://lkml.indiana.edu/hypermail /linux/kernel/0305.2/0697.html). – Str1101

+1

... Ho anche letto che ci sono alcune difficoltà riguardo all'implementazione di 'AIO', quindi forse è ancora più vantaggioso usare l'approccio' epoll' + pool di thread. [Che cosa è-the-differenze-tra ...] (http://stackoverflow.com/questions/5844955/whats-the-difference-between-event-driven-and-asynchronous-between-epoll-and-a). Mia idea è che sarebbe possibile utilizzare direttamente un thread del pool di passare fuori ogni connessione fino a quando il numero di connessioni simultanee si avvicina al numero massimo di thread che il sistema può sostenere, e quindi si potrebbe utilizzare la ... – Str1101

+1

epoll/kqueue/sistema AIO per gestire le nuove connessioni in entrata mentre tutti i thread sono occupati. (P.S .: Mi piacerebbe molto vedere il server presto, soprattutto se si è scritto in C++ :) – Str1101

51

Assolutamente. Un server standard può gestire più di connessioni simultanee 10K utilizzando il modello con un thread per connessione. Ho creato un'applicazione di questo tipo e cinque anni fa era in esecuzione con più di 50.000 connessioni simultanee per processo su un server Linux standard. Al giorno d'oggi, dovrebbe essere possibile eseguire la stessa applicazione con più di 250.000 connessioni simultanee sull'hardware corrente.

ci sono solo un paio di cose da tenere a mente:

  • discussioni riutilizzo utilizzando un pool di thread. Non è necessario eliminare i thread se non vengono utilizzati, poiché l'utilizzo delle risorse deve essere ottimizzato per i carichi di picco.
  • Dimensioni stack: per impostazione predefinita, ogni thread Linux riserva 8 MB per il relativo stack. Questo riassume fino a 80 GB per i thread 10K. È necessario impostare la dimensione dello stack predefinita su un valore compreso tra 64k e 512k, che non è un problema, poiché la maggior parte delle applicazioni non richiede stack di chiamate più profondi.
  • Se le connessioni sono di breve durata, ottimizzare per nuove connessioni creando più socket sullo stesso endpoint con l'opzione SO_REUSEPORT.
  • Aumentare i limiti utente: open files (valore predefinito 1.024), max user processes
  • Aumentare i limiti del sistema, ad es. /proc/sys/kernel/pid_max (predefinito 32 K), /proc/sys/kernel/threads-max e /proc/sys/vm/max_map_count (predefinito 65 K).

La domanda di cui sopra è stato inizialmente progettato per gestire solo 2K connessioni simultanee. Tuttavia, con la crescita in uso, non abbiamo dovuto apportare modifiche significative al codice per scalare fino a 50K connessioni.

+2

Questo potrebbe essere utile anche: https://gcc.gnu.org/wiki/SplitStacks – chbaker0

+0

Questo è essenzialmente utilizzando il sistema di programmazione filo come il sistema packet scheduling: filetto scheduler determina quale 'read()' per chiamare seguente secondo cui i dati arrivano Funziona, ovviamente, ma ci sono progetti più scalabili. –

Problemi correlati