Die Frage ist, was tatsächlich passiert, wenn Sie 1k-2k ausgehende HTTP-Anforderungen auslösen. Ich sehe, dass es alle Verbindungen mit 500 Verbindungen leicht lösen würde, aber das Aufsteigen von dort scheint Probleme zu verursachen, da die Verbindungen offen bleiben und die Node-App dort stecken bleibt. Getestet mit lokalem Server + Beispiel Google und anderen Mock-Servern.
Bei einigen verschiedenen Serverendpunkten erhielt ich einen Grund: Lesen Sie ECONNRESET, was in Ordnung ist. Der Server konnte die Anforderung nicht verarbeiten und einen Fehler auslösen. Im 1k-2k-Anforderungsbereich würde das Programm einfach hängen bleiben. Wenn Sie die offenen Verbindungen mit überprüfen, können lsof -r 2 -i -a
Sie feststellen, dass dort immer wieder X Verbindungen hängen 0t0 TCP 192.168.0.20:54831->lk-in-f100.1e100.net:https (ESTABLISHED)
. Wenn Sie Anforderungen eine Timeout-Einstellung hinzufügen, wird dies wahrscheinlich zu einem Timeout-Fehler führen. Warum wird die Verbindung sonst für immer aufrechterhalten und das Hauptprogramm befindet sich in einem Schwebezustand?
Beispielcode:
import fetch from 'node-fetch';
(async () => {
const promises = Array(1000).fill(1).map(async (_value, index) => {
const url = 'https://google.com';
const response = await fetch(url, {
// timeout: 15e3,
// headers: { Connection: 'keep-alive' }
});
if (response.statusText !== 'OK') {
console.log('No ok received', index);
}
return response;
})
try {
await Promise.all(promises);
} catch (e) {
console.error(e);
}
console.log('Done');
})();
quelle
npx envinfo
Beispiels veröffentlichen, das auf meinem Win 10 / nodev10.16.0-Skript ausgeführt wird und amAntworten:
Um zu verstehen, was sicher geschah, musste ich einige Änderungen an Ihrem Skript vornehmen, aber hier sind einige.
Zunächst wissen Sie vielleicht, wie
node
und wie esevent loop
funktioniert, aber lassen Sie mich kurz zusammenfassen. Wenn Sie ein Skript ausführen, führen Sie zurnode
Laufzeit zuerst den synchronen Teil davon aus und planen Sie dann diepromises
undtimers
, die in den nächsten Schleifen ausgeführt werden sollen. Wenn diese aktiviert sind, führen Sie die Rückrufe in einer anderen Schleife aus. Dieser einfache Kern erklärt es sehr gut, danke an @StephenGrider:In Ihrem Fall wird eine
async
Funktion ausgeführt, da immer ein Versprechen zurückgegeben wird und die Ausführung in der nächsten Schleifeniteration geplant wird. In Ihrer asynchronen Funktion planen Sie weitere 1000 Versprechen (HTTP-Anforderungen) gleichzeitig in diesermap
Iteration. Danach warten Sie darauf, dass alle aufgelöst werden, um das Programm zu beenden. Es wird sicher funktionieren, es sei denn, Ihre anonyme Pfeilfunktion auf demmap
löst keinen Fehler aus . Wenn einer Ihrer verspricht einen Fehler wirft und Sie nicht damit umgehen, wird ein Teil der Versprechungen nicht ihre Rückruf jemals das Programm machen namens müssen am Ende aber nicht zu Ausfahrt , weil die Ereignisschleife es zu verlassen , bis es Entschlüssen verhindern alle Aufgaben, auch ohne Rückruf. Wie es auf dem stehtPromise.all
docs : Es wird abgelehnt, sobald das erste Versprechen abgelehnt wird.Ihr On-
ECONNRESET
Fehler hängt also nicht mit dem Knoten selbst zusammen, sondern mit Ihrem Netzwerk, das den Abruf veranlasst hat, einen Fehler auszulösen und dann zu verhindern, dass die Ereignisschleife endet. Mit diesem kleinen Fix können Sie sehen, dass alle Anforderungen asynchron aufgelöst werden:quelle