Какво е Node.js? Обяснено е изпълнението на JavaScript

Мащабируемостта, латентността и производителността са ключови показатели за ефективност на уеб сървърите. Поддържането на ниска латентност и висока производителност при мащабиране и намаляване не е лесно. Node.js е среда за изпълнение на JavaScript, която постига ниска латентност и висока производителност, като използва „неблокиращ“ подход към обслужването на заявките. С други думи, Node.js не губи време или ресурси за изчакване на I / O заявките да се върнат.

В традиционния подход за създаване на уеб сървъри, за всяка входяща заявка или връзка сървърът поражда нова нишка на изпълнение или дори форкира нов процес за обработка на заявката и изпращане на отговор. Концептуално това е напълно логично, но на практика има много режийни разходи.

Докато хвърлящите хайвери изискват по-малко памет и процесорни разходи, отколкото процесите на разклоняване , това все още може да бъде неефективно. Наличието на голям брой нишки може да накара силно натоварената система да прекара ценни цикли за планиране на нишки и превключване на контекста, което добавя латентност и налага ограничения върху мащабируемостта и производителността.

Node.js използва различен подход. Той изпълнява еднопоточен цикъл на събития, регистриран в системата за обработка на връзки, и всяка нова връзка предизвиква задействане на функция за обратно извикване на JavaScript . Функцията за обратно извикване може да обработва заявки с неблокиращи I / O повиквания и, ако е необходимо, може да създаде нишки от пула, за да изпълнява блокиращи или CPU-интензивни операции и да балансира натоварването в процесорните ядра. Подходът на Node за мащабиране с функции за обратно извикване изисква по-малко памет за обработка на повече връзки, отколкото повечето конкурентни архитектури, които се мащабират с нишки, включително Apache HTTP Server, различните сървъри за приложения на Java, IIS и ASP.NET и Ruby on Rails.

Node.js се оказва доста полезен за настолни приложения в допълнение към сървърите. Също така имайте предвид, че приложенията на Node не са ограничени до чист JavaScript. Можете да използвате всеки език, който се транспилира в JavaScript, например TypeScript и CoffeeScript. Node.js включва JavaScript механизма на Google Chrome V8, който поддържа синтаксиса на ECMAScript 2015 (ES6), без да е необходим транпилатор ES6 към ES5 като Babel.

Голяма част от помощната програма на Node идва от голямата библиотека с пакети, която е достъпна от npmкомандата. NPM, мениджърът на пакети Node, е част от стандартната инсталация на Node.js, въпреки че има собствен уебсайт.

История на JavaScript

През 1995 г. Брендън Айх, тогава изпълнител на Netscape, създаде езика JavaScript, който да работи в уеб браузърите - за 10 дни, както продължава историята. JavaScript първоначално беше предназначен да позволи анимации и други манипулации на обектния модел на документ на браузъра (DOM). Версия на JavaScript за Netscape Enterprise Server беше представена малко след това.

Името JavaScript е избрано за маркетингови цели, тъй като по това време езикът на Java на Sun е широко разпространен. Всъщност езикът JavaScript всъщност се основаваше предимно на езиците Scheme и Self, с повърхностна Java-подобна семантика.

Първоначално много програмисти отхвърлиха JavaScript като безполезен за „реална работа“, тъй като неговият интерпретатор работеше с порядък по-бавно от компилираните езици. Това се промени, тъй като няколко изследователски усилия, насочени към ускоряване на JavaScript, започнаха да дават плодове. Най-видното е, че JavaScript двигателят на Google Chrome V8 с отворен код, който прави компилация точно в момента, вграждане и динамична оптимизация на кода, всъщност може да превъзхожда C ++ кода за някои товари и превъзхожда Python за повечето случаи на използване.

Базираната на JavaScript платформа Node.js е въведена през 2009 г. от Райън Дал за Linux и MacOS, като по-мащабируема алтернатива на Apache HTTP сървъра. NPM, написан от Isaac Schlueter, стартиран през 2010 г. Родната версия на Windows на Node.js дебютира през 2011 г.

Joyent притежаваше, управляваше и поддържаше усилията за разработка на Node.js в продължение на много години. През 2015 г. проектът Node.js беше предаден на фондацията Node.js и се управлява от техническия ръководен комитет на фондацията. Node.js също беше възприет като съвместен проект на Linux Foundation. През 2019 г. фондацията Node.js и JS се обединиха, за да образуват фондация OpenJS.

Основна архитектура Node.js

На високо ниво Node.js съчетава JavaScript V8 на Google V8, еднонишко неблокиращо събитие и I / O API на ниско ниво. Разделеният примерен код, показан по-долу, илюстрира основния модел на HTTP сървър, като използва функциите на стрелките ES6 (анонимни функции на Lambda, декларирани с помощта на оператора за дебела стрелка, =>) за обратно извикване.

Началото на кода зарежда HTTP модула, задава hostnameпроменливата на сървъра на localhost(127.0.0.1) и задава portпроменливата на 3000. След това създава сървър и функция за обратно извикване, в този случай функция на мастна стрелка, която винаги връща същото отговор на всяка заявка: statusCode200 (успех), обикновен текст от тип съдържание и текстов отговор на ”Hello World\n”. И накрая, той казва на сървъра да слуша на localhostпорт 3000 (чрез сокет) и дефинира обратно повикване за отпечатване на дневник на конзолата, когато сървърът е започнал да слуша. Ако стартирате този код в терминал или конзола с помощта на nodeкомандата и след това прегледате localhost: 3000 с помощта на който и да е уеб браузър на същата машина, ще видите “Hello World” във вашия браузър. За да спрете сървъра, натиснете Control-C в прозореца на терминала.

Имайте предвид, че всяко обаждане, направено в този пример, е асинхронно и не блокиращо. Функциите за обратно извикване се извикват в отговор на събития. На createServerтелефонния секретар дръжки събитие искане на клиента и връща отговор. На listenтелефонния секретар дръжки на listeningсъбитието.

Библиотеката Node.js

Както можете да видите отляво на фигурата по-долу, Node.js има широк набор от функционалности в своята библиотека. HTTP модулът, който използвахме в примерния код по-рано, съдържа както клиентски, така и сървърни класове, както можете да видите в дясната страна на фигурата. Функционалността на HTTPS сървъра, използваща TLS или SSL, живее в отделен модул.

Един присъщ проблем с еднонишковия цикъл на събития е липсата на вертикално мащабиране, тъй като нишката на цикъла на събитията ще използва само едно ядро ​​на процесора. Междувременно съвременните процесорни чипове често излагат осем или повече ядра, а съвременните сървърни стелажи често имат множество процесорни чипове. Приложение с една нишка няма да се възползва в пълна степен от 24-ядрените ядра в стабилна сървърна стойка.

Можете да поправите това, въпреки че е необходимо допълнително програмиране. Като начало Node.js може да създава дъщерни процеси и да поддържа тръби между родителя и децата, подобно на начина, по който системното popen(3)повикване работи, използвайки child_process.spawn() и свързани методи.

Модулът на клъстера е дори по-интересен от модула на дъщерния процес за създаване на мащабируеми сървъри. На cluster.fork()процесите метод хайвера си работници, които споделят сървърни портове на компанията-майка, като се използват child_process.spawn()под завивките. Главният клъстер разпределя входящите връзки между своите работници, използвайки по подразбиране алгоритъм с кръг, който е чувствителен към натоварванията на работния процес.

Имайте предвид, че Node.js не предоставя логика за маршрутизиране. Ако искате да поддържате състояние на връзките в клъстер, ще трябва да запазите обектите на сесията и влизането си някъде, различно от работната RAM.

Екосистемата на пакета Node.js

Регистърът на NPM е домакин на повече от 1,2 милиона пакета безплатен код за многократна употреба Node.js, което го прави най-големият софтуерен регистър в света. Имайте предвид, че повечето NPM пакети (по същество папки или елементи от системния регистър на NPM, съдържащи програма, описана от файл package.json), съдържат множество модули (програми, които зареждате с requireизрази). Лесно е да объркате двата термина, но в този контекст те имат специфични значения и не трябва да се разменят.

NPM може да управлява пакети, които са локални зависимости на конкретен проект, както и глобално инсталирани инструменти на JavaScript. Когато се използва като мениджър на зависимости за локален проект, NPM може да инсталира в една команда всички зависимости на проект чрез файла package.json. Когато се използва за глобални инсталации, NPM често изисква системни (судо) привилегии.

Не е нужно да използвате командния ред на NPM за достъп до публичния регистър на NPM. Други мениджъри на пакети като преждата на Facebook предлагат алтернативни клиентски преживявания. Можете също така да търсите и разглеждате пакети, като използвате уебсайта на NPM.

Защо искате да използвате NPM пакет? В много случаи инсталирането на пакет чрез командния ред на NPM е най-бързото и удобно за получаване на най-новата стабилна версия на модул, работещ във вашата среда, и обикновено е по-малко работа от клонирането на хранилището на източника и изграждането на инсталация от хранилището. Ако не искате най-новата версия, можете да зададете номер на версията на NPM, което е особено полезно, когато един пакет зависи от друг пакет и може да се скъса с по-нова версия на зависимостта.

Например, рамката Express, минимална и гъвкава рамка за уеб приложения Node.js, осигурява надежден набор от функции за изграждане на едно и много страници и хибридни уеб приложения. Докато лесното за клониране хранилище на Expresscode се намира на //github.com/expressjs/express, а експресната документация е на //expressjs.com/, бърз начин да започнете да използвате Express е да го инсталирате във вече инициализирана локална работна разработка директория с npmкомандата, например:

$ npm install express —save

В —saveопцията, която всъщност е включена по подразбиране в NPM 5.0 и по-късно, казва мениджъра на пакети, за да добавите модул Express към списъка на зависимости във файла package.json след инсталацията.

Друг бърз начин да започнете да използвате Express е да инсталирате изпълним генераторexpress(1) глобално и след това да го използвате, за да създадете приложението локално в нова работна папка:

$ npm install -g express-generator @ 4

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

С постигнатото, можете да използвате NPM, за да инсталирате всички необходими зависимости и да стартирате сървъра въз основа на съдържанието на файла package.json, създаден от генератора:

$ npm инсталиране

$ npm старт

Трудно е да се изберат акценти от милионните пакети в NPM, но няколко категории се открояват. Express е най-старият и най-виден пример за Node.js рамки. Друга голяма категория в хранилището на NPM са помощните програми за разработка на JavaScript, включително browserify, модулен пакет; bower, мениджър на пакети на браузъра; grunt, бегачът на задачи на JavaScript; и глътка, системата за изграждане на стрийминг. И накрая, важна категория за корпоративните разработчици на Node.js са клиентите на бази данни, от които има повече от 8000, включително популярни модули като redis, mongoose, firebase и pg, клиентът на PostgreSQL.

За да обобщим, Node.js е междуплатформена среда за изпълнение на JavaScript за сървъри и приложения. Той е изграден върху еднонишев, неблокиращ цикъл на събития, JavaScript механизма на Google Chrome V8 и API за входно / изходно ниво на ниско ниво. Различни техники, включително клъстерния модул, позволяват на приложенията Node.js да се мащабират повече от едно ядро ​​на процесора. Освен основната си функционалност, Node.js е вдъхновил екосистема от повече от милион пакета, които са регистрирани и версирани в хранилището на NPM и могат да бъдат инсталирани с помощта на командния ред на NPM или алтернатива като Yarn.