Wat is Node.js? De JavaScript-runtime uitgelegd

Schaalbaarheid, latentie en doorvoer zijn belangrijke prestatie-indicatoren voor webservers. De latentie laag en de doorvoer hoog houden tijdens het opschalen en uitschalen is niet eenvoudig. Node.js is een JavaScript-runtime-omgeving die een lage latentie en een hoge doorvoersnelheid bereikt door een "niet-blokkerende" benadering te volgen bij het verwerken van verzoeken. Met andere woorden, Node.js verspilt geen tijd of middelen aan het wachten tot I / O-verzoeken worden geretourneerd.

In de traditionele benadering van het creëren van web-servers, voor elke inkomende verzoeken of de verbinding van de server spawnt een nieuwe draad van de uitvoering of zelfs vorken een nieuw proces om het verzoek te behandelen en een antwoord sturen. Conceptueel is dit volkomen logisch, maar in de praktijk brengt het veel overhead met zich mee.

Hoewel spawning- threads minder geheugen en CPU-overhead met zich meebrengen dan forking- processen , kan het nog steeds inefficiënt zijn. De aanwezigheid van een groot aantal threads kan ertoe leiden dat een zwaarbelast systeem kostbare cycli besteedt aan threadplanning en contextomschakeling, wat de latentie vergroot en de schaalbaarheid en doorvoer beperkt.

Node.js heeft een andere benadering. Het voert een gebeurtenislus met één thread uit die bij het systeem is geregistreerd om verbindingen af ​​te handelen, en elke nieuwe verbinding zorgt ervoor dat een JavaScript- callback-functie wordt geactiveerd. De callback-functie kan verzoeken afhandelen met niet-blokkerende I / O-aanroepen, en kan indien nodig threads uit een pool voortbrengen om blokkerende of CPU-intensieve bewerkingen uit te voeren en om de belasting over CPU-kernen te verdelen. Node's benadering van schalen met callback-functies vereist minder geheugen om meer verbindingen te verwerken dan de meeste concurrerende architecturen die schalen met threads, waaronder Apache HTTP Server, de verschillende Java-applicatieservers, IIS en ASP.NET en Ruby on Rails.

Node.js blijkt best handig te zijn voor desktopapplicaties naast servers. Merk ook op dat Node-toepassingen niet beperkt zijn tot puur JavaScript. U kunt elke taal gebruiken die naar JavaScript wordt getransporteerd, bijvoorbeeld TypeScript en CoffeeScript. Node.js bevat de Google Chrome V8 JavaScript-engine, die de ECMAScript 2015 (ES6) -syntaxis ondersteunt zonder dat er een ES6-naar-ES5-transpiler zoals Babel nodig is.

Een groot deel van het hulpprogramma van Node is afkomstig van de grote pakketbibliotheek, die toegankelijk is via de npmopdracht. NPM, de Node-pakketbeheerder, maakt deel uit van de standaard Node.js-installatie, hoewel het een eigen website heeft.

Wat JavaScript-geschiedenis

In 1995 creëerde Brendan Eich, toen een aannemer van Netscape, de JavaScript-taal om in webbrowsers te draaien - in 10 dagen, zoals het verhaal gaat. JavaScript was oorspronkelijk bedoeld om animaties en andere manipulaties van het browser document object model (DOM) mogelijk te maken. Kort daarna werd een versie van JavaScript voor de Netscape Enterprise Server geïntroduceerd.

De naam JavaScript werd gekozen voor marketingdoeleinden, omdat de Java-taal van Sun in die tijd veel werd gehyped. In feite was de JavaScript-taal eigenlijk voornamelijk gebaseerd op de talen Scheme en Self, met oppervlakkige Java-achtige semantiek.

Aanvankelijk beschouwden veel programmeurs JavaScript als nutteloos voor "echt werk" omdat de interpreter een orde van grootte langzamer werkte dan gecompileerde talen. Dat veranderde toen verschillende onderzoeksinspanningen om JavaScript sneller te maken, vruchten begonnen af ​​te werpen. Het meest opvallend is dat de open-source Google Chrome V8 JavaScript-engine, die just-in-time compilatie, inlining en dynamische code-optimalisatie uitvoert, C ++ -code voor sommige belastingen kan overtreffen en in de meeste gevallen beter presteert dan Python.

Het op JavaScript gebaseerde Node.js-platform werd in 2009 geïntroduceerd door Ryan Dahl voor Linux en MacOS, als een beter schaalbaar alternatief voor de Apache HTTP-server. NPM, geschreven door Isaac Schlueter, gelanceerd in 2010. Een native Windows-versie van Node.js debuteerde in 2011.

Joyent was jarenlang eigenaar van, bestuurde en ondersteunde de ontwikkelingsinspanningen van Node.js. In 2015 werd het Node.js-project overgedragen aan de Node.js Foundation en werd het bestuurd door de technische stuurgroep van de stichting. Node.js werd ook omarmd als een Linux Foundation Collaborative Project. In 2019 zijn de Node.js Foundation en JS Foundation samengevoegd tot de OpenJS Foundation.

Basis Node.js-architectuur

Op een hoog niveau combineert Node.js de Google V8 JavaScript-engine, een single-threaded non-blocking event loop en een low-level I / O API. De uitgeklede voorbeeldcode die hieronder wordt weergegeven, illustreert het basispatroon van de HTTP-server, met behulp van ES6-pijlfuncties (anonieme Lambda-functies gedeclareerd met behulp van de fat arrow-operator =>) voor de callbacks.

Het begin van de code laadt de HTTP-module, stelt de servervariabele in hostnameop localhost(127.0.0.1) en stelt de portvariabele in op 3000. Vervolgens maakt het een server en een callback-functie aan, in dit geval een fat arrow-functie die altijd hetzelfde teruggeeft antwoord op elk verzoek: statusCode200 (geslaagd), inhoudstype platte tekst en een tekstreactie van ”Hello World\n”. Ten slotte vertelt het de server om te luisteren op localhostpoort 3000 (via een socket) en definieert het een callback om een ​​logbericht op de console af te drukken wanneer de server is begonnen met luisteren. Als u deze code in een terminal of console uitvoert met behulp van de nodeopdracht en vervolgens naar localhost: 3000 bladert met een webbrowser op dezelfde computer, ziet u "Hallo wereld" in uw browser. Om de server te stoppen, drukt u op Control-C in het terminalvenster.

Merk op dat elke oproep in dit voorbeeld asynchroon en niet-blokkerend is. De callback-functies worden aangeroepen als reactie op gebeurtenissen. De createServercallback behandelt een clientverzoekgebeurtenis en retourneert een reactie. De listencallback handelt de listeninggebeurtenis af.

De Node.js-bibliotheek

Zoals je aan de linkerkant in de onderstaande afbeelding kunt zien, heeft Node.js een groot aantal functies in zijn bibliotheek. De HTTP-module die we eerder in de voorbeeldcode hebben gebruikt, bevat zowel client- als serverklassen, zoals u aan de rechterkant van de afbeelding kunt zien. De HTTPS-serverfunctionaliteit die TLS of SSL gebruikt, leeft in een aparte module.

Een inherent probleem met een gebeurtenislus met één thread is een gebrek aan verticale schaalvergroting, aangezien de thread van de gebeurtenislus slechts één CPU-kern gebruikt. Ondertussen stellen moderne CPU-chips vaak acht of meer cores bloot, en moderne serverracks hebben vaak meerdere CPU-chips. Een single-threaded applicatie zal niet optimaal profiteren van de meer dan 24 cores in een robuust serverrack.

U kunt dat oplossen, hoewel het enige extra programmering vereist. Om te beginnen kan Node.js kindprocessen spawnen en leidingen tussen de ouder en de kinderen onderhouden, vergelijkbaar met de manier waarop de systeemaanroep popen(3)werkt, met behulp van child_process.spawn() en gerelateerde methoden.

De clustermodule is nog interessanter dan de onderliggende procesmodule voor het maken van schaalbare servers. De cluster.fork()methode brengt werkprocessen voort die de serverpoorten van de ouders delen, met behulp van child_process.spawn()onder de dekens. De clustermaster verdeelt inkomende verbindingen onder zijn werknemers met behulp van standaard een round-robin-algoritme dat gevoelig is voor belasting van werkprocessen.

Merk op dat Node.js geen routeringslogica biedt. Als u de status van alle verbindingen in een cluster wilt behouden, moet u uw sessie- en aanmeldingsobjecten op een andere plaats dan werkgeheugen-RAM bewaren.

Het ecosysteem van het Node.js-pakket

Het NPM-register bevat meer dan 1,2 miljoen pakketten gratis, herbruikbare Node.js-code, waardoor het het grootste softwareregister ter wereld is. Merk op dat de meeste NPM- pakketten (in wezen mappen of NPM-registeritems die een programma bevatten dat wordt beschreven door een package.json-bestand) meerdere modules bevatten (programma's die u laadt met requireinstructies). Het is gemakkelijk om de twee termen te verwarren, maar in deze context hebben ze een specifieke betekenis en mogen ze niet worden uitgewisseld.

NPM kan pakketten beheren die lokale afhankelijkheden zijn van een bepaald project, evenals wereldwijd geïnstalleerde JavaScript-tools. Bij gebruik als afhankelijkheidsbeheerder voor een lokaal project, kan NPM in één opdracht alle afhankelijkheden van een project installeren via het bestand package.json. Bij gebruik voor globale installaties vereist NPM vaak systeem (sudo) privileges.

Je hoeft niet hebben om de NPM opdrachtregel gebruiken om toegang te krijgen tot het publiek NPM register. Andere pakketbeheerders zoals Facebook's Yarn bieden alternatieve klantervaringen. U kunt ook zoeken en bladeren naar pakketten met behulp van de NPM-website.

Waarom zou je een NPM-pakket willen gebruiken? In veel gevallen is het installeren van een pakket via de NPM-opdrachtregel de snelste en handigste om de nieuwste stabiele versie van een module in uw omgeving te laten draaien, en is doorgaans minder werk dan het klonen van de bronrepository en het bouwen van een installatie vanuit de repository. Als u niet de laatste versie wilt, kunt u een versienummer opgeven voor NPM, wat vooral handig is wanneer het ene pakket afhankelijk is van een ander pakket en mogelijk breekt met een nieuwere versie van de afhankelijkheid.

Het Express-framework, een minimaal en flexibel Node.js-webapplicatieframework, biedt bijvoorbeeld een robuuste set functies voor het bouwen van single- en multi-page en hybride webapplicaties. Hoewel de gemakkelijk te klonen Expresscode-repository zich bevindt op //github.com/expressjs/express en de Express-documentatie zich op //expressjs.com/ bevindt, is een snelle manier om Express te gaan gebruiken door het te installeren in een reeds geïnitialiseerde lokale werkomgeving. directory met het npmcommando, bijvoorbeeld:

$ npm install express - opslaan

De —saveoptie, die standaard is ingeschakeld in NPM 5.0 en hoger, vertelt de pakketbeheerder om de Express-module na installatie toe te voegen aan de lijst met afhankelijkheden in het bestand package.json.

Een andere snelle manier om Express te gebruiken, is door de uitvoerbare generatorexpress(1) globaal te installeren en deze vervolgens te gebruiken om de applicatie lokaal in een nieuwe werkmap te maken:

$ npm install -g express-generator @ 4

$ express / tmp / foo && cd / tmp / foo

Als dat is bereikt, kunt u NPM gebruiken om alle benodigde afhankelijkheden te installeren en de server te starten, op basis van de inhoud van het package.json-bestand gemaakt door de generator:

$ npm installeren

$ npm start

Het is moeilijk om hoogtepunten te kiezen uit de miljoenen pakketten in de NPM, maar een paar categorieën vallen op. Express is het oudste en meest prominente voorbeeld van Node.js-frameworks. Een andere grote categorie in de NPM-repository zijn JavaScript-ontwikkelingshulpprogramma's, waaronder browserify, een modulebundler; bower, de browserpakketbeheerder; grunt, de JavaScript-taakrunner; en slok, het streaming build-systeem. Ten slotte is een belangrijke categorie voor enterprise Node.js-ontwikkelaars de databaseclients, waarvan er meer dan 8.000 zijn, inclusief populaire modules zoals redis, mongoose, firebase en pg, de PostgreSQL-client.

Samenvattend is Node.js een cross-platform JavaScript-runtime-omgeving voor servers en applicaties. Het is gebouwd op een single-threaded, niet-blokkerende event loop, de Google Chrome V8 JavaScript-engine en een low-level I / O API. Met verschillende technieken, waaronder de clustermodule, kunnen Node.js-apps verder worden geschaald dan een enkele CPU-kern. Naast de kernfunctionaliteit heeft Node.js een ecosysteem geïnspireerd van meer dan een miljoen pakketten die zijn geregistreerd en versiebeheer in de NPM-repository en kunnen worden geïnstalleerd met behulp van de NPM-opdrachtregel of een alternatief zoals Yarn.