"Blokkeer de event loop niet..." - je hebt deze zin waarschijnlijk al vaak gehoord... Het verbaast me niets, want het is een van de belangrijkste aannames bij het werken met Node. Maar er is ook een tweede "ding" dat je niet zou moeten blokkeren - de Worker Pool. Als het wordt verwaarloosd, kan het een aanzienlijke invloed hebben op de prestaties van de applicatie en zelfs op de veiligheid ervan.
Draden
Het belangrijkste om te onthouden: er zijn twee soorten draden in Node.js: Main Thread - die wordt afgehandeld door Gebeurtenis lusen Werknemerspool (threadpool) - dit is de pool van threads - de pool van threads.
dankzij libuv. Elk van hen heeft een andere taak. Het doel van de eerste is om niet-blokkerende I/O operaties af te handelen, en de tweede is verantwoordelijk voor CPU intensief werk en ook blokkerende I/O.

Maar wat is een thread en wat is het verschil met een proces? Er zijn verschillende verschillen, maar de belangrijkste voor ons is hoe het geheugen wordt toegewezen. Je kunt een proces zien als een applicatie. Binnen elk proces is er een stuk geheugen speciaal voor dit proces. Dus, het ene proces heeft geen toegang tot het geheugen van het andere, en deze eigenschap zorgt voor een hoge veiligheid. Om communicatie tussen hen tot stand te brengen, moeten we wat werk verrichten. Threads zijn anders. Threads draaien binnen een proces en delen hetzelfde geheugen, dus er is geen enkel probleem met threads die gegevens delen.
Er is echter één probleem. Het heet de "race condition". De threads kunnen tegelijkertijd draaien, dus hoe weten we welke als eerste eindigt? Het kan gebeuren dat de eerste keer dat je het uitvoert, de eerste bewerking als eerste eindigt, en de volgende keer kan het omgekeerd zijn en eindigt de tweede bewerking voor de eerste. Stel je voor dat je werkt met schrijf/lees operaties onder zulke omstandigheden! Een nachtmerrie! Het is soms erg moeilijk om correcte code in een omgeving met meerdere threads.
Bovendien hebben de multi-threaded talen een grote geheugenoverhead omdat ze voor elke aanvraag een aparte thread aanmaken; dus als je 1000 aanvragen wilt aanroepen, maken ze 1000 threads aan.
Hoe ga je om met zo'n probleem? Gebruik in plaats daarvan een enkele draad! En dat is wat Knooppunt biedt je.

Als JavaScript ontwikkelaar Ik moedig je aan om de film
waarin Bart Belder het concept van de event loop duidelijk uitlegt. Het bovenstaande diagram komt uit zijn presentatie. En als je deze termen helemaal niet kent, beide Knooppunt en Libuv hebben uitstekende documentatie 🙂
Over blokkeren
In JavaScript ontwikkeling industrie zeggen ze dat omdat Knooppunt single-threaded en non-blocking is, kun je een hogere gelijktijdigheid bereiken met dezelfde bronnen dan met multi-threaded oplossingen. Het is waar, maar het is niet zo mooi en gemakkelijk als het lijkt.
Sinds Node.js single-threaded is (JS-gedeelte), zullen CPU-intensieve taken alle lopende verzoeken blokkeren totdat de specifieke taak is voltooid. Het is dus waar dat in Node.js kun je elk verzoek blokkeren, alleen maar omdat een ervan een blokkeringsinstructie bevatte. De blokkeringscode betekent dat het meer dan een paar milliseconden duurt voordat het klaar is. Maar verwar lange reactietijd niet met blokkeren. Het antwoord van de database kan erg lang duren, maar het blokkeert je proces (applicatie) niet.
Blokkerende methoden worden synchroon uitgevoerd en niet-blokkerende methoden worden asynchroon uitgevoerd.
Hoe kun je je gebeurtenissenlus vertragen (of blokkeren)?
- Kwetsbare regex - een kwetsbare reguliere uitdrukking is een uitdrukking waarbij je reguliere uitdrukkingsengine exponentiële tijd nodig kan hebben; je kunt er meer over lezen hier,
- JSON-bewerkingen op grote objecten,
- met behulp van synchrone API's van Knooppunt kernmodules in plaats van async versies; alle I/O methodes in de Node.js standaardbibliotheek bieden ook hun asynchrone versies,
- andere programmeerfouten, zoals synchrone oneindige lussen.
In dat geval, aangezien de Worker Pool een pool van threads gebruikt, is het dan mogelijk om deze ook te blokkeren? Helaas, ja 🙁 Knooppunt is gebaseerd op een filosofie één thread voor veel klanten.
Laten we aannemen dat een bepaalde taak die wordt uitgevoerd door een specifieke Worker erg complex is en meer tijd nodig heeft om te worden voltooid. Als gevolg daarvan wordt de Worker geblokkeerd en kan deze niet worden gebruikt om andere taken uit te voeren totdat zijn instructies zijn uitgevoerd. Zoals je waarschijnlijk al hebt geraden, kan dit de prestaties beïnvloeden. Je kunt dergelijke problemen voorkomen door de variatie in Taak-tijden te minimaliseren door Taak-partitionering te gebruiken.
Conclusie
Vermijd blokkeren, dat is zeker. Als je alleen kunt, kies dan altijd voor asynchrone versies van de standaardbibliotheek-API's. Anders kan de client na het uitvoeren van je app verschillende problemen ondervinden, beginnend met de verminderde doorvoer en eindigend met volledige terugtrekking, wat fataal is vanuit het perspectief van de gebruiker.
Lees meer:
Waarom je (waarschijnlijk) Typescript zou moeten gebruiken
Hoe help je een project niet om zeep met slechte codeerpraktijken?
Strategieën voor het ophalen van gegevens in NextJS