2010-08-22 13 views
11

Il nostro server analitico è scritto in C++. In pratica, interroga il motore di archiviazione sottostante e restituisce dati strutturati piuttosto grandi tramite parsimonia. Una richiesta tipica richiederà da 0,05 a 0,6 secondi per finire dipende dalla dimensione della richiesta.TNonblockingServer, TThreadedServer e TThreadPoolServer, quale si adatta meglio al mio caso?

Ho notato che ci sono alcune opzioni in termini di server Thrift che possiamo usare nel codice C++, in particolare TNonblockingServer, TThreadedServer e TThreadPoolServer. Sembra che TNonblockingServer sia la strada da percorrere poiché può supportare molte più richieste simultanee e continuare a utilizzare un pool di thread dietro la scena per crunch attraverso le attività. Evita anche il costo di costruzione/distruzione dei thread.

aggiornamento di Facebook sul risparmio: http://www.facebook.com/note.php?note_id=16787213919

Qui a Facebook, stiamo lavorando su un client completamente asincrono e il server per C++. Questo server utilizza l'I/O basato sugli eventi come TNonblockingServer corrente, ma la sua interfaccia su il codice dell'applicazione si basa tutto su callback asincroni. Questo ci consentirà di scrivere server che possono servire migliaia di richieste simultanee (ognuna delle quali richiede effettuare chiamate ad altri server Thrift o Memcache) con pochi thread.

Post relativi stackover: Large number of simulteneous connections in thrift

Detto questo, non sarà necessariamente in grado di fare effettivamente lavorare più velocemente (gestori ancora eseguire in un pool di thread), ma più clienti sarà in grado di connettersi a voi in una sola volta.

Basta chiedersi ci sono altri fattori che mi mancano qui? Come posso decidere quale si adatta meglio alle mie esigenze?

risposta

5

Le richieste che richiedono da 50 a 600 millisecondi per completare sono piuttosto lunghe. Il tempo necessario per creare o distruggere un thread è molto inferiore a quello, quindi non lasciare che questo fattore nella tua decisione in questo momento. Sceglierei quello che è più facile da supportare e che è il meno incline agli errori. Vuoi minimizzare la probabilità di subdoli bug di concorrenza.

Questo è il motivo per cui è spesso più semplice scrivere codice di gestione transazioni a thread singolo che blocca dove è necessario e che molti di questi sono in esecuzione in parallelo rispetto a un modello non bloccante più complesso. Un thread bloccato può rallentare una singola transazione, ma non impedisce al server di eseguire altri lavori mentre è in attesa.

Se il carico della transazione aumenta (vale a dire più transazioni client) o le richieste diventano più veloci da elaborare (circa 1 millisecondo per transazione), il sovraccarico della transazione diventa più di un fattore. La metrica su cui prestare attenzione è la velocità effettiva: quante transazioni vengono completate per unità di tempo. La durata assoluta di una singola transazione è meno importante della velocità con cui vengono completati, almeno se rimane ben al di sotto di un secondo.

4

Un ragazzo su Github ha fatto un bel confronto

TThreadedServer

TThreadedServer genera un nuovo thread per ogni connessione client, e ogni thread rimane in vita fino a quando la connessione client viene chiusa.Ciò significa che se ci sono 1000 connessioni client simultanee, TThreadedServer deve eseguire simultaneamente 1000 thread.

TNonblockingServer

TNonblockingServer ha un thread dedicato per l'I/O. Lo stesso thread può anche elaborare le richieste, oppure è possibile creare un pool separato di thread di lavoro per l'elaborazione delle richieste. Il server può gestire molte connessioni simultanee con un numero limitato di thread poiché non è necessario generare un nuovo thread per ciascuna connessione.

TThreadPoolServer (non indicizzata qui)

TThreadPoolServer è simile a TThreadedServer; ogni connessione client ottiene il proprio thread dedicato del server. È diverso da TThreadedServer in 2 modi:

Il thread del server ritorna al pool di thread dopo che il client ha chiuso la connessione per il riutilizzo. C'è un limite al numero di thread. Il pool di thread non crescerà oltre il limite. Il client si blocca se non c'è più thread disponibile nel pool di thread. È molto più difficile da usare rispetto agli altri 2 server.