Node.js friert weiterhin ein, wenn Sie CPU-Arbeit im Haupt-Thread ausführen_
Node ist hervorragend im nicht blockierenden I/O, aber synchrone CPU-intensive Operationen blockieren weiterhin den Ereignis-Loop. Diese Unterscheidung ist der Ursprung vieler Vorfälle in der Produktion.
Node.js ist gut in der I/O-Konkurrenz. Es ist nicht gut darin, CPU-Arbeit als asynchron darzustellen, nur weil die Handler-Funktion async verwendet.
Diese Unterscheidung ist wichtig, denn viele Leistungsprobleme stammen nicht von langsamen Datenbanken oder langsamen Netzwerken. Sie entstehen durch eine Anfrage, die zu viel synchrone Arbeit verrichtet, während jede andere Anfrage dahinter wartet.
Das Irreführende Beispiel
Diese Route sieht auf den ersten Blick harmlos aus:
Der Datenbankaufruf ist asynchron. JSON.parse ist es nicht.
Wenn die Nutzlast groß ist, erfolgt das Parsen im Haupt-Thread, und der Ereignis-Loop kann andere eingehende Anfragen nicht bedienen, bis diese Arbeit abgeschlossen ist.
Was Tatsächlich Blockiert
In realen Node-Diensten sind die üblichen Übeltäter:
große JSON.parse und JSON.stringify Aufrufe
Bild- oder PDF-Erstellung
Krypto-Arbeiten an der falschen Stelle
große synchrone Dateioperationen
teure Regex- oder Transformationsschleifen
Die Lösung ist nicht "alles asynchron machen". Die Lösung besteht darin, die Arbeit zu verlagern oder umzugestalten.
Bessere Optionen
Wann immer möglich:
streamen Sie anstelle von Puffern großer Nutzlasten
verwenden Sie Worker für CPU-intensive Aufgaben
verlagern Sie teure Transformationen aus heißen Anforderungswegen
Zum Beispiel sind Worker-Threads oft die sauberere Grenze für rechenintensive Operationen:
import { Worker } from "node:worker_threads";export function runHeavyTask(input: unknown) { return new Promise((resolve, reject) => { const worker = new Worker(new URL("./worker.js", import.meta.url), { workerData: input, }); worker.once("message", resolve); worker.once("error", reject); });}
Das macht die Arbeit nicht günstiger. Es hält den Ereignis-Loop reaktionsschnell, während die Arbeit woanders geschieht.
Der Kompromiss
Node ist immer noch eine gute Wahl für viele Backendsysteme. Sie müssen nur das Laufzeitmodell respektieren. Wenn Ihr Dienst die meiste Zeit mit dem Warten auf I/O verbringt, passt Node natürlich. Wenn er die meiste Zeit mit der Verarbeitung von Daten auf der CPU verbringt, benötigen Sie eine überlegte Isolation.