Was ist nicht blockierende oder asynchrone E / A in Node.js?

136

Was ist im Kontext von serverseitigen Javascript-Engines nicht blockierende E / A oder asynchrone E / A. Ich sehe dies als einen Vorteil gegenüber serverseitigen Java-Implementierungen.

Anand
quelle
3
Es ist hilfreich, über Skript-Tags in der Browser-Umgebung nachzudenken, um dieses Konzept zu verstehen. Zakas hat einen großartigen Artikel darüber - die ersten Abschnitte sollten ausreichen, um das Konzept des Blockierens zu erklären: nczonline.net/blog/2010/08/10/what-is-a-non-blocking-script
netpoetica

Antworten:

316

Synchron vs Asynchron

Die synchrone Ausführung bezieht sich normalerweise auf Code, der nacheinander ausgeführt wird. Asynchrone Ausführung bezieht sich auf die Ausführung, die nicht in der Reihenfolge ausgeführt wird, in der sie im Code angezeigt wird. Im folgenden Beispiel bewirkt der synchrone Betrieb, dass die Warnungen nacheinander ausgelöst werden. Während der asynchronen Operation alert(2)die zweite Ausführung ausgeführt wird, ist dies nicht der Fall.

Synchron: 1,2,3

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

Asynchron: 1,3,2

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

Blockieren vs Nicht blockieren

Das Blockieren bezieht sich auf Operationen, die die weitere Ausführung blockieren, bis diese Operation abgeschlossen ist. Nicht blockierend bezieht sich auf Code, der die Ausführung nicht blockiert. In dem angegebenen Beispiel localStoragehandelt es sich um eine Blockierungsoperation, da die Ausführung zum Lesen blockiert wird. Auf der anderen Seite fetchhandelt es sich um eine nicht blockierende Operation, da die alert(3)Ausführung nicht blockiert wird .

// 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);

Vorteile

Ein Vorteil nicht blockierender asynchroner Vorgänge besteht darin, dass Sie die Nutzung einer einzelnen CPU sowie des Arbeitsspeichers maximieren können.

Beispiel für synchrones Blockieren

Ein Beispiel für synchrone Blockierungsvorgänge ist die Verarbeitung von E / A- oder Netzwerkanforderungen durch einige Webserver wie in Java oder PHP. Wenn Ihr Code aus einer Datei oder der Datenbank liest, "blockiert" Ihr Code alles, was danach ausgeführt wird. In diesem Zeitraum hält Ihr Computer an Speicher und Verarbeitungszeit für einen Thread fest , der nichts tut .

Um andere Anforderungen zu erfüllen, während dieser Thread blockiert ist, hängt dies von Ihrer Software ab. Die meisten Server-Software-Programme erzeugen mehr Threads, um die zusätzlichen Anforderungen zu erfüllen. Dies erfordert mehr Speicherverbrauch und mehr Verarbeitung.

Asynchrones, nicht blockierendes Beispiel

Asynchrone, nicht blockierende Server - wie die in Node erstellten - verwenden nur einen Thread, um alle Anforderungen zu bearbeiten. Dies bedeutet, dass eine Instanz von Node das Beste aus einem einzelnen Thread herausholt. Die Entwickler haben es mit der Prämisse entworfen, dass die E / A- und Netzwerkoperationen der Engpass sind.

Wenn Anforderungen auf dem Server eintreffen, werden sie einzeln bearbeitet. Wenn der zu wartende Code beispielsweise die Datenbank abfragen muss, sendet er den Rückruf an eine zweite Warteschlange und der Hauptthread wird weiter ausgeführt (er wartet nicht). Wenn der DB-Vorgang abgeschlossen ist und zurückkehrt, wird der entsprechende Rückruf aus der zweiten Warteschlange gezogen und in eine dritte Warteschlange gestellt, in der die Ausführung aussteht. Wenn die Engine die Möglichkeit erhält, etwas anderes auszuführen (z. B. wenn der Ausführungsstapel geleert wird), nimmt sie einen Rückruf aus der dritten Warteschlange auf und führt ihn aus.

Joseph
quelle
5
Ich bin nicht sicher, ob ich Ihren zweiten Absatz unter Blockieren in PHP verstehe . Wollen Sie damit sagen: "Während PHP normalerweise E / A blockiert, ist dies nicht der Fall, weil das Betriebssystem E / A-Vorgänge automatisch fädelt." Oder sagen Sie, dass dies kein Problem in PHP ist, weil PHP automatisch einen neuen Thread für jede Anforderung erstellt, damit eine blockierte Anforderung nicht die gesamte PHP-Umgebung anhält? (Ich
vermute
6
Es ist das letztere.
Joseph
2
Warten Sie, wenn es sich um letzteres handelt, welche Vorteile nicht blockierendes E / A-PHP (wie ReactPHP oder etwas anderes) gegenüber dem blockierenden hat. immer noch verwirren
Sunu Pinasthika Fajar
5
@CharlieParker Ja. Die asynchrone Operation wird parallel zu Ihrem Code ausgeführt. Der Rückruf, der zu den Ergebnissen der asynchronen Operation "zurückkehrt", wird jedoch zur Ausführung im Hauptcode in die Warteschlange gestellt, wenn der Hauptcode nicht belegt ist.
Joseph
2
@CharlieParker Hier ist ein Beitrag , der mehr über die Interna des Async-Mechanismus behandelt.
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

Codebeispiel

Wayne Chiu
quelle