2011-01-21 3 views
16

Sto cercando di capire cosa rende Nginx così veloce e ho alcune domande.nginx: il suo multithreading ma utilizza più processi?

Come ho capito, Apache genera un nuovo processo per servire ogni richiesta O genera un nuovo thread per servire ogni richiesta. Poiché ogni nuovo thread condivide lo spazio degli indirizzi virtuali, l'utilizzo della memoria continua a salire se ci sono un certo numero di richieste simultanee.

Nginx risolve questo problema con un solo processo di ascolto (Master), con un singolo thread di esecuzione AND 2 o 3 (numero è configurabile) processi di lavoro. Questo processo/thread master sta eseguendo un ciclo di eventi. In attesa di qualsiasi richiesta in arrivo. Quando arriva una richiesta, dà quella richiesta a uno dei processi di lavoro.

favore correggetemi se la mia comprensione di cui sopra non è corretta

Se quanto sopra è corretto, quindi ho un paio di domande:

1.) Non è il processo di lavoro di andare a deporre le uova più thread e andando a correre lo stesso problema di Apache?

2.) O è veloce nginx perché la sua architettura basata sugli eventi utilizza IO non bloccante al di sotto di tutto. Forse il processo di lavoro genera thread che fanno solo non-blocking-IO, è così?

3.) Che "esattamente" è "architettura basata su eventi", qualcuno può davvero semplificarlo, perché soemone come me capire. Riguarda solo il non-blocco-io o qualcos'altro?

Ho ottenuto un riferimento di c10k, sto provando ad analizzarlo, ma non penso sia relativo all'archivio basato sugli eventi. sembra più per IO non bloccante.

+0

L'I/O non bloccante richiede un'architettura basata su eventi. –

+0

FYI - Nel caso tu sia interessato a scavare più a fondo - ho scritto la risposta con altri materiali + video qui: http://planetunknown.blogspot.com/2011/02/why-nginx-is-faster- than-apache.html – PlanetUnknown

risposta

17

Non è molto complicato da un punto di vista concettuale. Cercherò di essere chiaro ma devo fare qualche semplificazione.

I server basati su eventi (come nginx e lighttpd) utilizzano un wrapper attorno a un sistema di monitoraggio degli eventi. Per esempio. lighttpd utilizza libevent per astrarre il sistema di monitoraggio degli eventi ad alta velocità più avanzato (vedere anche libev).

Il server tiene traccia di tutte le connessioni non bloccanti che ha (sia in scrittura che in lettura) utilizzando una semplice macchina a stati per ciascuna connessione. Il sistema di monitoraggio degli eventi notifica il processo del server quando sono disponibili nuovi dati o quando è possibile scrivere più dati. È come un select() su steroidi, se si conosce la programmazione socket. Il processo del server quindi invia semplicemente il file richiesto utilizzando alcune funzioni avanzate come sendfile() ove possibile o trasforma la richiesta in un processo CGI utilizzando un socket per la comunicazione (questa presa verrà monitorata con il sistema di monitoraggio degli eventi come le altre connessioni di rete.)

This collegamento come un sacco di grandi informazioni sugli interni di nginx, per ogni evenienza. Spero possa essere d'aiuto.

+0

Grazie a Ass3mbler. Penso che questo abbia aiutato a comprenderlo. – PlanetUnknown

+0

@PlanetUnknow Sono davvero contento che sia stato d'aiuto. Se hai bisogno di maggiori informazioni, chiedimi, ho lavorato molte volte per modificare la fonte di lighttpd. Se è ok, puoi accettare la mia risposta per favore? Grazie! – Ass3mbler

+0

Grazie a Ass3mbler. Penso che questo abbia aiutato a comprenderlo. Pertanto, il processo principale è in ascolto del traffico in entrata e i processi di lavoro eseguono cicli di eventi (registrazione degli eventi e risposta quando si verifica uno). In un riassunto, è corretto? – PlanetUnknown

46

Apache utilizza più thread per fornire ogni richiesta con il proprio thread di esecuzione. Questo è necessario per evitare il blocco quando si utilizza l'I/O sincrono.

Nginx utilizza solo I/O asincrono, il che rende il blocco di un problema. L'unico motivo per cui nginx utilizza più processi, è quello di sfruttare appieno i sistemi multi-core, multi-CPU e iper-threading. Anche con il supporto SMP, il kernel non può pianificare un singolo thread di esecuzione su più CPU.Richiede almeno un processo o thread per CPU logica.

Quindi la differenza è, nginx richiede solo processi di lavoro sufficiente per ottenere il beneficio completo di SMP, mentre l'architettura di Apache rende necessario la creazione di un nuovo thread (ciascuno con il proprio stack di circa ~ 8MB) per ogni richiesta. Ovviamente, a concorrenza elevata, Apache utilizzerà molta più memoria e subirà un sovraccarico maggiore dal mantenimento di un numero elevato di thread.

+3

risposta molto chiara! – clime

+0

Perché non utilizzare più thread per utilizzare CPU multi-core? – spockwang

+0

@spockwang Infatti usano un lavoratore per il core. _ ** La configurazione NGINX consigliata nella maggior parte dei casi - l'esecuzione di un processo di lavoro per core della CPU - rende l'uso più efficiente delle risorse hardware. ** _ dai [documenti NGINX] (https://www.nginx.com/blog/inside -nginx-how-we-designed-for-performance-scale) – gabrielgiussi

6

Apache non genera un nuovo thread per ogni richiesta. Mantiene una cache di thread o un gruppo di processi pre-forked a cui invia richieste. Il numero di richieste concorrenti è limitato dal numero di figli/thread sì, ma apache non genera un nuovo thread/figlio per ogni richiesta che sarebbe ridicolmente lento (anche con thread, creazione e rimozione per ogni richiesta sarebbe troppo lento)

Nginx utilizza un modello master-worker. Il processo principale riguarda il caricamento della configurazione e la creazione/distruzione/manutenzione dei lavoratori. Come apache, inizia con un numero di processi pre-fork già in esecuzione ognuno dei quali è un worker (e uno dei quali è il processo "master"). CIASCUNO processo di lavoro condivide una serie di socket di ascolto. Ogni processo di lavoro accetta le connessioni e le elabora, ma ogni lavoratore può gestire migliaia di connessioni contemporaneamente, a differenza di Apache che può gestire solo 1 connessione per operatore.

Il modo in cui nginx raggiunge questo è attraverso "multiplexing". Non usa libevent, usa un ciclo di eventi personalizzato che è stato progettato specificamente per nginx e cresciuto nello sviluppo con lo sviluppo del software nginx. Il multiplexing funziona usando un loop per "incrementare" attraverso un blocco di programma da un blocco che funziona su un pezzo di dati/nuova connessione/qualunque per connessione/oggetto per iterazione del ciclo. È tutto basato su backend come Epoll() kqueue() e select(). Che dovresti leggere su