Предисловие
В наши дни платформа Node.Js является одной из самых распространённых платформ для построения эффектных и масштабируемых REST API's, а также подходит для построения мобильных приложений, десктопных программ.
Node.Js – среда выполнения JavaScript, основанная на движке V8 Chrome.
V8 ускоряет JavaScript, используя C ++ V8 – движок с открытым исходным кодом, написанный на C ++.JavaScript - V8 (C ++) - машинный код V8 реализует сценарий ECMAScript, как указано в ECMA-262. ECMAScript был создан Ecma International для стандартизации JavaScript. V8 может работать автономно или может быть встроен в любое приложение C ++. Благодаря этому, вы можете написать свой собственный код на C ++, и сделать его доступным для JavaScript.
Node.Js – использует управляемую событиями, неблокирующую модель ввода – вывода, которая делает ее легкой и эффективной.
Пакетная система Node.Js, npm, является самой большой экосистемой библиотек с открытым исходным кодом в мире.
Мир до Node.Js
Веб – приложения которые написаны следуя клиент – серверной архитектуре, работают по следующей схеме – клиент запрашивает нужный ресурс у сервера и сервер отправляет ресурс в ответ. В этой схеме сервер, ответит на запрос, прерывает соединение.
Такая модель эффективна потому что, каждый запрос к серверу тратит ресурсы (память, процессорное время и т.д.). Для того чтобы обрабатывать каждый последующий запрос от клиента, сервер должен завершить обработку предыдущего. Когда сервер получает новый запрос он создает отдельный поток для его обработки.
Поток – это время и ресурсы, что CPU выделяет на выполнение небольшого блока инструкций. С учетом сказанного, сервер может обрабатывать несколько запросов одновременно, но только по одному на поток. Для обработки N запросов серверу нужно N потоков. Если сервер получает N+1 запрос, тогда он должен ждать пока один из потоков не станет доступен.
Один из способов избавиться от ограничений – добавить ресурсов (память, ядер процессора, частоту и т.д.)
Неблокирующий ввод – вывод и асинхронное выполнение.
Синхронное выполнение обычно ссылается на выполнение кода в последовательности. Асинхронное выполнение относится к выполнению, которое не выполняется в последовательности, в коде.
Блокировка относится к операциям, которые блокируют дальнейшее выполнение до завершения этой операции. Неблокирование относится к коду, который не блокирует выполнение кода.
Одним из преимуществ неблокирующих асинхронных операций является то, что вы можете максимизировать использование как одного потока, так и процессора, и памяти.
Примером синхронных, блокирующих операций является то, как некоторые веб-серверы, подобные тем, что в Java или PHP обрабатывают ввод – вывод или сетевые запросы. Если ваш код читается из файла или БД, ваш код блокирует все после его выполнения. В этот период ваша машина удерживает память и время обработки потока, который ничего не делает.
Чтобы удовлетворить другие запросы, пока этот поток застопорился, зависит от вашего ПО. То, что делает большинство серверных программ, порождает больше потоков для удовлетворения дополнительных запросов. Это требует большого объема памяти и большей обработки.
Однако, сервера которые созданы с помощью Node.Js, используют только один поток для обслуживания всех запросов. Это означает что Node использует максимально один поток. Создатели спроектировали его с предпосылкой, что операции ввода вывода и сети являются узким местом.
Когда запросы поступают на сервер, они обслуживаются по одному за раз. Однако, когда обслуживаемый код должен запрашивать БД, например, он отправляет обратный вызов ко второй очереди, и основной поток будет продолжать работать (он не ждет). Теперь, когда операция БД завершается и возвращается, соответствующий обратный вызов вытаскивается из второй очереди и помещается в очередь в третьей очереди, где они находятся в ожидании выполнения. Когда у движка появляется шанс выполнить что-то еще, он подбирает обратный вызов из третьей очереди и выполняет его.
Цикл событий
Цикл событий— это магия, которая происходит внутри Node.js. Это буквально бесконечный цикл и на самом деле один поток.
Libuv— C библиотека которая реализует этот паттерн и является частью ядра Node.js.
Кратко работу Eevent loop можно описать так: операция передается на выполнения ядру системы, после завершения Node js получает уведомление в том, что определенная для операции callback-функция может быть добавлена в очередь выполнения.
Инициализация event loop происходит в момент запуска сервера Node js, и с этого момента он начинает свою работу, которую можно разделить на несколько этапов:
timers - выполнение callback-функций, зарегистрированных функциями setTimeout() и setInterval();
pending callbacks - вызов callback-функций операций ввода/вывода, выполнение которых было отложено на предыдущей стадии цикла событий;
idle, prepare - выполнение внутренних действий, необходимых самому Node js event loop;
poll - выполнение callback-функций завершенных асинхронных операций и управление фазой timers;
check - выполнение callback-функций, зарегистрированных функцией setImmediate();
close callbacks - обработка внезапно завершающихся действий.
Обратите внимание, когда циклу событий нужно выполнить операцию ввода/вывода он использует поток ОС с тредпула (thread pool), а когда задача выполнена, коллбэк ставится в очередь во время фазы pending callbacks.
В заключении хотелось бы сказать, что NodeJs – это мощная технология, которую стоит изучить при возможности.
Библиографический список
Сухов К.К. Node.Js. Путеводитель по технологии, - М, ДМК Пресс, 2015. 416с.: ил
Habr: [сайт] – URL: https://habr.com/ru/post/460661/(дата обращения: 20.01.2020)
Habr: [сайт] – URL:https://habr.com/ru/post/420123/(дата обращения: 20.01.2020)
Пауэрс Ш. Изучаем Node.Js. – СПб.: Питер, 2014. – 400с: ил. – (Серия «Бестселлеры O’Reilly».