2009-05-26 15 views
9

I server Web non-forking (ovvero a thread singolo o select()) come lighttpd o nginx sono sempre più popolari.Come funziona un server Web non forking?

Mentre c'è una moltitudine di documenti che spiegano i server di forking (a vari livelli di dettaglio), la documentazione per i server non-forking è scarsa.

Sto cercando un occhi uccello vista come un server non-forking web funziona. (Pseudo-) codice o un diagramma macchina di stato, ridotto al minimo , sarebbe grande.

Sono consapevole delle seguenti risorse e le ho trovate utili.

Tuttavia, io sono interessato a dei principi, non i dettagli di implementazione.

In particolare:

  • Perché questo tipo di server a volte chiamata non bloccante, quando select() essenzialmente blocchi?

  • L'elaborazione di una richiesta può richiedere un po 'di tempo. Cosa succede con le nuove richieste durante questo periodo in cui non ci sono thread o processi specifici del listener? L'elaborazione della richiesta è in qualche modo interrotta o time-sliced?

Edit: A quanto mi risulta, mentre una richiesta viene elaborata (per esempio file letto o script CGI run) il server non può accettare nuove connessioni. Questo non significherebbe che un tale server potrebbe perdere molto di nuove connessioni se uno script CGI viene eseguito per, diciamo, 2 secondi o giù di lì?

+1

Mi piacerebbe pensare che un non-forking web server sarebbe una cattiva partita a qualsiasi server web che ha voluto al server più di una quantità insignificante di contenuto dinamico . – Eddie

+0

@Eddie Non per niente. Con n processori, avere più di n thread non ti permetterà di fare più lavoro. Un server asincrono progettato correttamente può fare tanto lavoro quanto un biforcarsi o uno threaded. –

+0

@Nick Johnson: dipende. Se si hanno N processori e N thread, nella misura in cui una qualsiasi richiesta blocca l'attesa per I/O, non si sta effettivamente utilizzando il processore a meno che non si creino più thread. Ad esempio, se devi andare al database per soddisfare una richiesta dinamica, quel thread viene fermato finché non ottieni una risposta. Con solo N thread, puoi trascorrere la maggior parte del tuo tempo in attesa e solo una piccola parte del tuo tempo viene effettivamente elaborata. – Eddie

risposta

8

pseudocodice base:

setup 
while true 
    select/poll/kqueue 
    with fd needing action do 
     read/write fd 
     if fd was read and well formed request in buffer 
      service request 
     other stuff 
  • Sebbene select() & amici bloccano, presa I/O non sta bloccando. Sei bloccato solo finché non hai qualcosa di divertente da fare.
  • L'elaborazione di singole richieste comportava normalmente la lettura di un descrittore di file da un file (risorsa statica) o processo (risorsa dinamica) e quindi dalla scrittura sul socket. Questo può essere fatto facilmente senza mantenere molti stati.
  • Quindi, service request significa in genere aprire un file, aggiungerlo all'elenco per select e notare che le informazioni lette da lì vanno a un determinato socket. Sostituire FastCGI per file quando appropriato.

EDIT:

  • Non sono sicuro circa le altre, ma nginx ha 2 processi: un master e un lavoratore. Il master esegue l'ascolto e quindi invia la connessione accettata all'operatore per l'elaborazione.
4

select() PLUS blocking I/O essenzialmente permette di gestire/rispondere a più connessioni come vengono in un unico filo (multiplexing), contro avente più thread/processi gestiscono una presa ciascuna. L'obiettivo è ridurre al minimo il rapporto tra l'impronta del server e il numero di connessioni.

È efficiente perché questo thread singolo sfrutta l'alto livello di connessioni socket attive necessarie per raggiungere la saturazione (dato che possiamo eseguire operazioni di I/O non bloccanti su più descrittori di file).

La logica è che richiede pochissimo tempo per riconoscere i byte disponibili, interpretarli, quindi decidere i byte appropriati da inserire nel flusso di output. L'effettivo lavoro di I/O viene gestito senza bloccare questo thread del server.

Questo tipo di server è sempre in attesa di una connessione, bloccando select(). Una volta ottenuto, gestisce la connessione, quindi rivisita select() in un ciclo infinito. Nel caso più semplice, questo thread del server NON blocca altre volte oltre a quando sta configurando l'I/O.

Se è presente una seconda connessione, verrà gestita la volta successiva che il server seleziona(). A questo punto, la prima connessione potrebbe ancora essere ricevuta e possiamo iniziare a inviare alla seconda connessione, dallo stesso thread del server. Questo è l'obiettivo

Cerca "multiplexing network sockets" per risorse aggiuntive.

Oppure provate programmazione di rete Unix da Stevens, Fenner, Rudoff