In che modo Nginx gestisce le sue richieste in termini di attività o thread?

1

Recentemente ho letto su Wikipedia su Nginx . Ciò che mi ha lasciato perplesso era questo paragrafo:

Nginx uses an asynchronous event-driven approach to handling requests, instead of the Apache HTTP Server model that defaults to a threaded or process-oriented approach, where the Event MPM is required for asynchronous processing. Nginx's modular event-driven architecture[18] can provide more predictable performance under high loads.

Ora capisco come funzionano entrambi gli approcci, event-driven e threaded / process-oriented. Ma quello che trovo confuso da questa affermazione è che anche approcci asincroni devono delegare il loro lavoro (una volta ricevuto) ad alcune attività / thread / processi dedicati.

O mi sbaglio?

    
posta user654123 17.09.2014 - 15:52
fonte

1 risposta

0

Ogni server che elabora le richieste in parallelo e condivide una fonte di input (ad es. una porta) deve delegare il lavoro in qualche modo. Se non si elaborano richieste in parallelo, si dispone di un servizio a thread singolo; se non condividi una fonte di input, hai una serie di servizi a thread singolo. La differenza tra i due modelli ha più a che fare con il modo in cui viene eseguito il lavoro rispetto a come viene delegato.

Il modello di processo o thread per task semplifica la manutenzione di una richiesta perché è possibile trattarla come un'attività lineare e lineare che viene eseguita dall'inizio alla fine e si interrompe quando è necessario attendere che accada qualcosa. Il compromesso è che ogni volta che l'attività blocca o il sistema operativo decide che la sua fascia temporale è scaduta, deve esserci un cambio di contesto tra ciò che è in esecuzione e ciò che sarà. Ogni ciclo che passi facendo un cambio di contesto è un ciclo che non puoi spendere facendo il lavoro, e ci possono essere molti di loro coinvolti nella manutenzione di una singola richiesta.

I programmi che si fatturano come eventi o asincroni tendono a trattare il lavoro come una unità di dati (cioè una struttura con informazioni sull'attività in corso) piuttosto che un'unità di esecuzione (cioè un processo o un thread). Ciò significa mettere in esecuzione thread di lavoro su più core che estraggono le unità di lavoro da una coda, gestire parte del lavoro come descritto dai dati e metterlo da parte fino a quando non accade la prossima cosa. Quando succederà la prossima cosa, qualunque sia stata rilevata, aggiorna semplicemente le informazioni dell'attività e la rimette in coda per essere gestita.

In questo modo si recupera tutto lo stato di gestione che è stato fatto dal sistema operativo e lo mette nelle mani del programma. Il lavoratore finisce per essere un po 'più complesso, ma poiché la gestione dello stato può essere adattata per l'applicazione, finisce per essere molto meno pasticciata (e quindi meno costosa) rispetto allo scambio di registro e stack all'ingrosso che si ottiene durante un cambio di contesto. Il sistema operativo può ancora forzare un commutatore di contesto o il thread può fornire volontariamente se ha esaurito il lavoro, ma uno di questi è un evento molto meno comune di quello che si otterrebbe per richiesta nel modello per-thread . Questa è una semplificazione eccessiva, poiché ci sono altre cose che puoi fare all'interno di questo modello per ottenere ancora di più dai processori che hai, ma sono al di fuori dello scopo di questa risposta.

Detto questo, è possibile scrivere un programma basato sugli eventi che utilizza il modello thread-per-task e avrà tutte le stesse inefficienze.

    
risposta data 17.09.2014 - 17:56
fonte

Leggi altre domande sui tag