Sergio è corretto. La tua app, a questo punto, è probabilmente migliore del tradizionale modello Apache/Passenger. Se si prende la rotta event, in particolare su piattaforme a thread singolo come Ruby, non è MAI possibile bloccare nulla, che si tratti dei server DB, Cache, di altre richieste HTTP che si potrebbero fare - nulla.
Questo è ciò che rende più difficile la programmazione asincrona (evento): è facile bloccare su roba, di solito sotto forma di I/O del disco sincrono o risoluzioni DNS. I framework non eventualizzati (evented) come nodejs fanno attenzione a non fornire (quasi) mai una chiamata della funzione framework che blocca, ma tutto viene gestito utilizzando i callback (incl le query DB).
Questo potrebbe essere più facile da visualizzare, se si guarda al cuore di un server non-blocking a thread singolo:
while(wait_on_sockets(/* list<socket> */ &$sockets, /* event */ &$what, $timeout)) {
foreach($socketsThatHaveActivity as $fd in $sockets) {
if($what == READ) { // There is data availabe to read from this socket
$data = readFromSocket($fd);
processDataQuicklyWithoutBlocking($data);
}
elseif ($what == WRITE && $data = dataToWrite($fd)) { // This socket is ready to be written to (if we have any data)
writeToSocket($fd, $data);
}
}
}
Quella che vedete sopra è chiamato il ciclo degli eventi. wait_on_sockets
viene solitamente fornito dal sistema operativo sotto forma di una chiamata di sistema, ad esempio selezionare, eseguire il polling, epoll o kqueue. Se processDataQuicklyWithoutBlocking impiega troppo tempo, il buffer di rete della tua applicazione gestito dal sistema operativo (nuove richieste, dati in entrata, ecc.) Si riempirà e causerà il rifiuto di nuove connessioni e il timeout di quelli esistenti, dato che $ socketsThatHaveActivity non viene gestito abbastanza velocemente . Questo è diverso da un server con thread (ad esempio un'installazione tipica di Apache) in quanto ogni connessione viene servita utilizzando un thread/processo separato, quindi i dati in arrivo verranno letti nell'app non appena arrivano e i dati in uscita verranno inviati senza ritardo .
Quali framework non bloccanti come nodejs fanno quando si effettua (ad esempio) una query DB è aggiungere la connessione socket del server DB all'elenco dei socket monitorati ($ socket), quindi anche se la query richiede un po ', il tuo thread (solo) non è bloccato su quella presa. Piuttosto, essi forniscono una richiamata:
$db.query("...sql...", function($result) { ..handle result ..});
Come potete vedere sopra, db.query restituisce immediatamente senza alcun blocco sul server db di sorta.Questo significa anche avere spesso di scrivere codice in questo modo, a meno che il linguaggio di programmazione in sé supporta le funzioni asincrone (come il nuovo C#):
$db.query("...sql...", function($result) { $httpResponse.write($result); $connection.close(); });
La regola mai-mai-blocco può essere un po 'rilassato se si dispone di molti processi che eseguono ognuno un ciclo di eventi (tipicamente il modo di eseguire un cluster di nodi), o usano un pool di thread per mantenere il loop degli eventi (java, netty ecc., puoi scrivere il tuo in C/C++). Mentre un thread è bloccato su qualcosa, altri thread possono ancora fare il ciclo degli eventi. Ma sotto carico abbastanza pesante, anche questi non riuscirebbero a funzionare. Quindi non avere MAI MAI BLOCCO in un server event.
Quindi, come potete vedere, i server eventi in genere cercano di risolvere un problema diverso - possono avere un gran numero di connessioni aperte. Dove eccellono è solo spingendo byte intorno con calcoli di luce (ad esempio server comet, cache come memcached, vernice, proxy come nginx, squid ecc.). Non vale nulla che, anche se scalano meglio, i tempi di risposta tendono generalmente ad aumentare (niente è meglio che riservare un'intera discussione per una connessione). Naturalmente, potrebbe non essere economicamente/computazionalmente fattibile eseguire lo stesso numero di thread di # connessioni simultanee.
Ora torniamo al tuo problema - ti raccomando di mantenere Nginx in circolazione, dato che è eccellente per la gestione delle connessioni (che è basata su eventi) - generalmente significa gestire i keep-alive HTTP, SSL ecc. Dovresti quindi connetterti alla tua app Rails che utilizza FastCGI, dove devi ancora eseguire i worker, ma non devi riscrivere la tua app per essere completamente evented. Dovresti anche consentire a Nginx di pubblicare contenuti statici, in nessun modo i dipendenti di Rails saranno legati a qualcosa che Nginx può normalmente fare meglio. Questo approccio generalmente scala molto meglio di Apache/Passenger, specialmente se si esegue un sito Web ad alto traffico.
Se riesci a scrivere l'intera app in modo da essere evento, allora è grandioso, ma non ho idea di quanto sia facile o difficile in Ruby.
Wow .. grazie per la risposta dettagliata Tejas. Quindi i parametri che leggo fuori dalla rete .. sono per un genere di applicazione completamente diverso? Il sito di Thin fornisce un'app per i binari come app di esempio per thin. http://code.macournoyer.com/thin/. Avevo l'impressione che potessi semplicemente sostituire il passeggero con un filo sottile e tutto sarebbe stato molto faticoso. –
Se non blocchi da nessuna parte, dovresti essere in grado di ricreare questi parametri di riferimento. – tejas