Vad är Node.js? JavaScript-körtiden förklaras

Skalbarhet, latens och genomströmning är viktiga prestandaindikatorer för webbservrar. Det är inte lätt att hålla latensen låg och genomströmningen hög medan du skalar upp och ut. Node.js är en JavaScript-runtime-miljö som uppnår låg latens och hög genomströmning genom att ta en "icke-blockerande" metod för att betjäna förfrågningar. Med andra ord slösar Node.js ingen tid eller resurser på att vänta på att I / O-förfrågningar ska återvända.

I den traditionella metoden att skapa webbservrar, för varje inkommande begäran eller anslutnings servern leker en ny tråd i utförandet eller ens gafflar en ny process för att hantera begäran och skicka ett svar. Konceptuellt är det här meningsfullt, men i praktiken medför det en hel del omkostnader.

Medan lekande trådar ådrar sig mindre minne och CPU overhead än forking processer , kan det fortfarande vara ineffektivt. Närvaron av ett stort antal trådar kan orsaka att ett tungt laddat system spenderar värdefulla cykler på trådschemaläggning och kontextbyte, vilket lägger till latens och sätter gränser för skalbarhet och genomströmning.

Node.js tar ett annat tillvägagångssätt. Den kör en händelsesslinga med en gänga som är registrerad i systemet för att hantera anslutningar och varje ny anslutning gör att en JavaScript- återuppringningsfunktion aktiveras. Återuppringningsfunktionen kan hantera förfrågningar med icke-blockerande I / O-samtal och kan vid behov skapa gängor från en pool för att utföra blockerande eller CPU-intensiva operationer och för att ladda balans över CPU-kärnor. Nodes tillvägagångssätt för skalning med återuppringningsfunktioner kräver mindre minne för att hantera fler anslutningar än de flesta konkurrenskraftiga arkitekturer som skalas med trådar, inklusive Apache HTTP-server, de olika Java-applikationsservrarna, IIS och ASP.NET och Ruby on Rails.

Node.js visar sig vara ganska användbart för skrivbordsapplikationer utöver servrar. Observera också att nodapplikationer inte är begränsade till ren JavaScript. Du kan använda vilket språk som helst som skickas till JavaScript, till exempel TypeScript och CoffeeScript. Node.js innehåller Google Chrome V8 JavaScript-motorn, som stöder syntax för ECMAScript 2015 (ES6) utan att behöva en ES6-till-ES5-sändare som Babel.

Mycket av Nodes verktyg kommer från dess stora paketbibliotek, som är tillgängligt från npmkommandot. NPM, Node-pakethanteraren, är en del av standardinstallationen Node.js, även om den har sin egen webbplats.

Några JavaScript-historik

1995 skapade Brendan Eich, då en entreprenör för Netscape, JavaScript-språket för att köras i webbläsare - på 10 dagar, som berättelsen går. JavaScript var ursprungligen avsett att möjliggöra animeringar och andra manipuleringar av webbläsarens dokumentobjektmodell (DOM). En version av JavaScript för Netscape Enterprise Server introducerades strax efteråt.

Namnet JavaScript valdes för marknadsföringsändamål, eftersom Suns Java-språk blev allmänt hypad vid den tiden. Faktum är att JavaScript-språket faktiskt huvudsakligen baserades på schemat och självspråk, med ytlig Java-liknande semantik.

Inledningsvis avfärdade många programmerare JavaScript som värdelöst för ”riktigt arbete” eftersom dess tolk körde en storleksordning långsammare än kompilerade språk. Det förändrades när flera forskningsinsatser som syftade till att göra JavaScript snabbare började bära frukt. Mest framträdande kan den öppna källkoden för Google Chrome V8 JavaScript, som gör just-in-time-sammanställning, inläggning och dynamisk kodoptimering, faktiskt överträffa C ++ - kod för vissa belastningar och överträffar Python för de flesta användningsfall.

Den JavaScript-baserade Node.js-plattformen introducerades 2009 av Ryan Dahl för Linux och MacOS som ett mer skalbart alternativ till Apache HTTP-servern. NPM, skriven av Isaac Schlueter, lanserades 2010. En inbyggd Windows-version av Node.js debuterade 2011.

Joyent ägde, styrde och stödde utvecklingen av Node.js under många år. 2015 överlämnades Node.js-projektet till Node.js Foundation och styrdes av stiftelsens tekniska styrkommitté. Node.js omfamnades också som ett Linux Foundation-samarbetsprojekt. År 2019 slogs Node.js Foundation och JS Foundation samman och bildade OpenJS Foundation.

Grundläggande Node.js-arkitektur

På hög nivå kombinerar Node.js Google V8 JavaScript-motorn, en entrådig icke-blockerande händelsesslinga och ett lågnivå I / O API. Den avskalade exempelkoden som visas nedan illustrerar det grundläggande HTTP-servermönstret med hjälp av ES6-pilfunktioner (anonyma Lambda-funktioner som deklareras med fettpiloperatören =>) för återuppringningarna.

Början på koden laddar HTTP-modulen, sätter servervariabeln hostnametill localhost(127.0.0.1) och sätter portvariabeln till 3000. Sedan skapas en server och en återuppringningsfunktion, i detta fall en fettpilfunktion som alltid returnerar samma svar på alla önskemål: statusCode200 (framgång), innehållstyp vanlig text och ett textsvar på ”Hello World\n”. Slutligen uppmanar den servern att lyssna på localhostport 3000 (via ett uttag) och definierar en återuppringning för att skriva ut ett loggmeddelande på konsolen när servern har börjat lyssna. Om du kör den här koden i en terminal eller konsol med nodekommandot och sedan bläddrar till localhost: 3000 med vilken webbläsare som helst på samma maskin ser du “Hello World” i din webbläsare. För att stoppa servern, tryck på Control-C i terminalfönstret.

Observera att alla samtal som görs i detta exempel är asynkrona och icke-blockerande. Återuppringningsfunktionerna anropas som svar på händelser. Den createServeråteruppringning hanterar en klientbegäran händelse och returnerar ett svar. Den listenåteruppringning hanterar listeninghändelsen.

Node.js-biblioteket

Som du kan se till vänster på figuren nedan har Node.js ett stort utbud av funktioner i sitt bibliotek. HTTP-modulen som vi använde i exempelkoden tidigare innehåller både klient- och serverklasser, som du kan se till höger om figuren. HTTPS-serverfunktionaliteten med TLS eller SSL lever i en separat modul.

Ett inneboende problem med en enda gängad händelsesslinga är bristen på vertikal skalning, eftersom händelsens looptråd endast använder en enda CPU-kärna. Samtidigt exponerar moderna CPU-chips ofta åtta eller fler kärnor, och moderna serverracks har ofta flera CPU-chips. En engängad applikation kommer inte att dra full nytta av de 24 plus-kärnorna i ett robust serverhack.

Du kan fixa det, även om det krävs ytterligare programmering. Till att börja med kan Node.js skapa barnprocesser och underhålla rör mellan föräldern och barnen, på samma sätt som popen(3)systemanropet fungerar, med hjälp av child_process.spawn() och relaterade metoder.

Klustermodulen är ännu mer intressant än den underordnade processmodulen för att skapa skalbara servrar. De cluster.fork()metod leker arbetsprocesser som delar moderserverportar hjälp child_process.spawn()under täcket. Klustermastern distribuerar inkommande anslutningar mellan sina arbetare med hjälp av en rund-robin-algoritm som är känslig för arbetsprocessbelastningar.

Observera att Node.js inte tillhandahåller routningslogik. Om du vill behålla tillståndet mellan anslutningar i ett kluster måste du behålla dina sessioner och inloggningsobjekt någon annanstans än RAM-minne.

Node.js-paketsekosystemet

NPM-registret är värd för mer än 1,2 miljoner paket med gratis, återanvändbar Node.js-kod, vilket gör det till det största programvaruregistret i världen. Observera att de flesta NPM- paket (i huvudsak mappar eller NPM-registerobjekt som innehåller ett program som beskrivs av en package.json-fil) innehåller flera moduler (program som du laddar med requireuttalanden). Det är lätt att förväxla de två termerna, men i detta sammanhang har de specifika betydelser och bör inte bytas ut.

NPM kan hantera paket som är lokala beroenden för ett visst projekt samt globalt installerade JavaScript-verktyg. När den används som en beroendeshanterare för ett lokalt projekt kan NPM installera, i ett kommando, alla beroenden i ett projekt genom filen package.json. När det används för globala installationer kräver NPM ofta systemrättigheter (sudo).

Du behöver inte ha att använda NPM kommandoraden för att få tillgång till den offentliga NPM registret. Andra pakethanterare som Facebooks Garn erbjuder alternativa upplevelser på klientsidan. Du kan också söka och bläddra efter paket med NPM: s webbplats.

Varför skulle du vilja använda ett NPM-paket? I många fall är installation av ett paket via NPM-kommandoraden det snabbaste och mest praktiska för att få den senaste stabila versionen av en modul som körs i din miljö, och det är vanligtvis mindre arbete än att klona källförvaret och bygga en installation från förvaret. Om du inte vill ha den senaste versionen kan du ange ett versionsnummer till NPM, vilket är särskilt användbart när ett paket beror på ett annat paket och kan bryta med en nyare version av beroendet.

Exempelvis tillhandahåller Express-ramverket, ett minimalt och flexibelt Node.js-webbapplikationsramverk, en robust uppsättning funktioner för att bygga enkla och flersidiga och hybridwebapplikationer. Medan det enkelt klonbara Expresscode-arkivet finns på //github.com/expressjs/express och Express-dokumentationen finns på //expressjs.com/, är ett snabbt sätt att börja använda Express att installera det i en redan initierad lokal arbetsutveckling katalog med npmkommandot, till exempel:

$ npm install express - spara

Den —savealternativ som faktiskt är aktiverat som standard i NPM 5.0 och senare, berättar pakethanteraren för att lägga till Express-modulen till listan beroenden i package.json filen efter installationen.

Ett annat snabbt sätt att börja använda Express är att installera den körbara generatornexpress(1) globalt och sedan använda den för att skapa applikationen lokalt i en ny arbetsmapp:

$ npm installera -g expressgenerator @ 4

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

Med det som uppnåtts kan du använda NPM för att installera alla nödvändiga beroenden och starta servern, baserat på innehållet i package.json-filen som skapats av generatorn:

$ npm installera

$ npm start

Det är svårt att välja höjdpunkter ur de miljoner pluspaketen i NPM, men några kategorier sticker ut. Express är det äldsta och mest framstående exemplet på Node.js-ramar. En annan stor kategori i NPM-förvaret är JavaScript-utvecklingsverktyg, inklusive browserify, en modulbuntare; bower, webbläsarens pakethanterare; grunt, JavaScript-aktivitetslöparen; och gulp, streaming-byggsystemet. Slutligen är en viktig kategori för företagets Node.js-utvecklare databasklienter, av vilka det finns mer än 8000, inklusive populära moduler som redis, mongoose, firebase och pg, PostgreSQL-klienten.

Sammanfattningsvis är Node.js en plattformsmässig JavaScript-runtime-miljö för servrar och applikationer. Den är byggd på en entrådig, icke-blockerande händelsesslinga, Google Chrome V8 JavaScript-motorn och ett I / O-API på låg nivå. Olika tekniker, inklusive klustermodulen, gör att Node.js-appar kan skala utöver en enda CPU-kärna. Utöver dess kärnfunktionalitet har Node.js inspirerat ett ekosystem med mer än en miljon paket som är registrerade och versionerade i NPM-förvaret och kan installeras med hjälp av NPM-kommandoraden eller ett alternativ som garn.