Che cos'è l'I / O non bloccante o asincrono in Node.js?


136

Nel contesto dei motori Javascript lato server, che cos'è l'I / O non bloccante o l'I / O asincrono? Vedo che questo è menzionato come un vantaggio rispetto alle implementazioni lato server Java.


3
È utile pensare ai tag degli script nell'ambiente del browser per comprendere questo concetto. Zakas ha pubblicato un ottimo articolo al riguardo: le prime sezioni dovrebbero essere sufficienti per spiegare il concetto di blocco: nczonline.net/blog/2010/08/10/what-is-a-non-blocking-script
netpoetica

Risposte:


317

Sincrono vs asincrono

L'esecuzione sincrona di solito si riferisce all'esecuzione del codice in sequenza. L'esecuzione asincrona si riferisce all'esecuzione che non viene eseguita nella sequenza visualizzata nel codice. Nel seguente esempio, l'operazione sincrona fa scattare gli avvisi in sequenza. Nell'operazione asincrona, mentre alert(2)sembra eseguire secondo, non lo fa.

Sincrono: 1,2,3

alert(1);
alert(2);
alert(3);

Asincrono: 1,3,2

alert(1);
setTimeout(() => alert(2), 0);
alert(3);

Blocco vs Non blocco

Il blocco si riferisce alle operazioni che bloccano l'ulteriore esecuzione fino al termine dell'operazione. Il non blocco si riferisce al codice che non blocca l'esecuzione. Nell'esempio dato, localStorageè un'operazione di blocco in quanto blocca l'esecuzione da leggere. D'altra parte, fetchè un'operazione non bloccante in quanto non si ferma alert(3)dall'esecuzione.

// Blocking: 1,... 2
alert(1);
var value = localStorage.getItem('foo');
alert(2);

// Non-blocking: 1, 3,... 2
alert(1);
fetch('example.com').then(() => alert(2));
alert(3);

vantaggi

Un vantaggio delle operazioni asincrone e non bloccanti è che è possibile massimizzare l'utilizzo di una singola CPU e della memoria.

Esempio di blocco sincrono

Un esempio di operazioni di blocco sincrono è il modo in cui alcuni server Web come quelli in Java o PHP gestiscono le richieste di IO o di rete. Se il tuo codice legge da un file o dal database, il tuo codice "blocca" qualsiasi cosa dopo l'esecuzione. In quel periodo, la tua macchina si tiene in memoria e il tempo di elaborazione per un thread che non sta facendo nulla .

Per soddisfare altre richieste mentre il thread è bloccato, dipende dal software. Quello che fa la maggior parte dei software server è generare più thread per soddisfare le richieste aggiuntive. Ciò richiede più memoria consumata e più elaborazione.

Esempio asincrono, non bloccante

I server asincroni e non bloccanti, come quelli realizzati in Node, utilizzano solo un thread per soddisfare tutte le richieste. Ciò significa che un'istanza di Node ottiene il massimo da un singolo thread. I creatori lo hanno progettato con la premessa che l'I / O e le operazioni di rete sono il collo di bottiglia.

Quando le richieste arrivano al server, vengono gestite una alla volta. Tuttavia, quando ad esempio il codice servito deve interrogare il DB, invia il callback a una seconda coda e il thread principale continuerà a funzionare (non attende). Ora, quando l'operazione DB viene completata e restituita, il callback corrispondente viene estratto dalla seconda coda e messo in coda in una terza coda in cui sono in attesa di esecuzione. Quando il motore ha la possibilità di eseguire qualcos'altro (come quando lo stack di esecuzione viene svuotato), raccoglie un callback dalla terza coda e lo esegue.


5
Non sono sicuro di aver compreso il tuo secondo paragrafo sotto Blocco in PHP . Stai dicendo che "Sebbene PHP normalmente si blocchi su IO, non lo fa perché il sistema operativo esegue automaticamente il thread delle operazioni IO". Oppure stai dicendo che questo non è un problema in PHP perché PHP crea automaticamente un nuovo thread per ogni richiesta in modo che una richiesta bloccata non interrompa l'intero ambiente PHP? (Immagino che quest'ultimo ..)
dc

6
È quest'ultimo.
Joseph,

2
aspetta, se è il secondo, quali sono i vantaggi I / O PHP non bloccanti (come un reagente PHP o qualcos'altro) rispetto a quello bloccante. ancora confuso
Sunu Pinasthika Fajar

5
@CharlieParker Sì. L'operazione asincrona viene eseguita parallelamente al codice. Ma il callback che "ritorna" ai risultati dell'operazione asincrona viene messo in coda per l'esecuzione nel codice principale quando il codice principale non è occupato.
Joseph,

2
@CharlieParker Ecco un post che tratta di più sugli interni del meccanismo asincrono.
Joseph,

7
var startTime = new Date().getTime();
var getEndTime = () => {
    var tempEndTime = new Date().getTime();
    var second = (tempEndTime - startTime)/1000
    return `took ${second} sec...to finish\n`
}

console.log('1: start App', getEndTime())
setTimeout(()=>{
    console.log('2: setTimeout', getEndTime())
}, 1000)
console.log('3: End App', getEndTime())

// console -> Process Order:  1 -> 3 -> 2

Esempio di codice

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.