"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.

But what is a thread and how it’s different than a process? There are several differences, but the most important one for us is how the memory is allocated to them. You can think about a process like about an application. Inside each process, there is a chunk of memory dedicated just for this process. So, one process doesn`t have access to the memory of the second one, and this property ensures high security. To establish communication between them, we must do some work. Threads are different. Threads runs inside a process and share the same memory so there is no problem at all with threads sharing data.
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