Как работает node js

Почему Node.js — это гуд

Краткое введение в платформу, на которой JavaScript покоряет мир.

  1. Вы написали простое приложение в браузере — например, анализатор текста или ипотечный калькулятор. Так как всё было в браузере, вы сразу написали всё на JavaScript. Софт работает, приносит пользу.
  2. Со временем вы развиваете проект. Появляются новые функции. Однажды появилась потребность в переносе программы на мощный сервер. Например, вы решили добавить к своему софту интеграцию с Телеграмом, а для этого нужен сервер.
  3. В обычной ситуации вам бы пришлось выбрать какой-нибудь серверный язык и написать свой софт заново — например, на Python или PHP. Но благодаря NodeJS можно скопипастить существующий код, переписав лишь ввод-вывод, и ваша программа продолжит покорять мир.

Это и есть Node.js.

Что такое Node.js

Node.js — это система, которая исполняет JavaScript отдельно от вашего браузера. Можно сказать, что это самостоятельная среда для выполнения JavaScript.

Node.js можно установить на сервер (так же, как Python) и исполнять на нём ваш код, отдавая результат исполнения пользователям. На нём же можно делать отдельные приложения, используя дополнительные фреймворки.

Чем хорош Node.js

Если вы начинали изучать программирование, вам будет понятна концепция последовательного исполнения программы. Сначала исполняется первая строчка, потом вторая, потом третья и так далее. Может быть, где-то программа прыгнет вперёд-назад, где-то закольцуется, но в целом она исполняется линейно.

У JS есть фишка — он умеет исполнять код параллельно (условно говоря). Программисты называют это обработкой событий. Программе можно сказать: «Если когда-нибудь произойдёт вот это — выполните вон ту функцию, она знает, что делать». Таких событий можно предусмотреть много — получается, процессы как будто параллельны. Программа может просто сидеть и ждать, когда что-то произойдёт.

Больше того, процессы асинхронны: программа может что-то запросить в самом начале работы — например, спросить что-то у базы данных. И пока база данных чешется, программа на Node.js будет заниматься дальше своими делами. А как придёт ответ — возьмёт его и обработает.

При разработке любой программы на Node.js могут возникнуть сотни таких параллельных событий и обработчиков. Чтобы никто из них не перетягивал одеяло на себя, Node.js делает бесконечный цикл, в котором по кругу предоставляет процессорное время каждой функции. В результате создаётся иллюзия, что они работают параллельно и не мешают друг другу, но на самом деле ими жёстко управляет сама платформа.

Именно такое равномерное распределение всего в цикле событий и даёт Node.js преимущество при создании серверных приложений.

Пример: веб-сервер на Node.js

Как работает обычный веб-сервер

Раньше была такая проблема:

  1. На странице нужно, например, показать аватарку и никнейм пользователя.
  2. Для этого сервер делал запрос к базе данных, чтобы получить оттуда эту информацию.
  3. Пока база не ответит, сервер ничего не может сделать — он терпеливо ждёт.
  4. Сервер ждёт.
  5. Когда от базы приходит ответ с картинкой и никнеймом, сервер снова оживает, продолжает загружать страницу и в самом конце запрашивает у базы фоновую картинку для сайта.
  6. Сервер ждёт
  7. Страница тоже пока не работает, потому что не загрузилась до конца. Половина скриптов тоже не работают, потому что они ждут полной загрузки страницы. Все ждут, пока база ответит.
  8. На каждый такой запрос нужны ресурсы, чтобы держать соединение с базой.
  9. Если таких запросов много, ресурсы на сервере быстро заканчиваются, и тогда сайт начинает тормозить у всех сразу.
  10. Сервер начинает тупить и иногда вываливается с ошибкой. Страницы падают, пользователи психуют и уходят на другой сайт.

Как работает сервер на Node.js

  1. На странице нужно, например, показать аватарку и никнейм пользователя.
  2. Для этого сервер делает запрос к базе данных, чтобы получить оттуда эту информацию, а сам продолжает формировать страницу дальше.
  3. Пока не пришла аватарка, сервер уже сделал всё остальное и увидел, что нужна фоновая картинка.
  4. Сервер запрашивает картинку, а в это время ему пришла аватарка из прошлого запроса. Раз аватарка пришла, сервер вставляет её на нужное место. Пока он это делал — пришла фоновая картинка.
  5. Все материалы на месте, можно показывать страницу пользователю. Страница загружается быстрее, потому что сборка произошла параллельно.

Для чего ещё нужен Node.js

Кроме веб-приложений этот язык используют для создания любых сервисов, где нужен постоянный обмен информацией с пользователем:

  • чаты,
  • социальные сети,
  • системы совместной работы над проектом,
  • онлайн-редакторы текста.

А ещё на нём можно написать практически любое приложение и запустить его под Windows, MacOs или Linux. Это можно использовать для разработки универсальных приложений, например, списка задач, который должен работать на всех платформах, синхронизировать данные в реальном времени и уметь отправлять всё на мобильное устройство.

Node.js для фронтенд-разработчиков

Это руководство ориентировано на разработчиков, которые знают JavaScript, но еще не очень хорошо владеют Node.

Вам, вероятно, уже приходится работать с Node.js: npm scripts, конфигурацией webpack, задачами gulp, автоматической сборкой и запуском тестов. Несмотря на то, что для работы не требуется глубокое понимание всех этих действий, иногда они могут сбивать с толку.

Познакомившись с Node.js поближе, вы сможете во всем разобраться, а заодно автоматизировать некоторые вещи, которые до сих пор делаете вручную. Вы почувствуете себя увереннее и сможете писать более сложные сценарии.

Версия Node

Самое разительное отличие серверного программирования от клиентского заключается в том, что вы сами определяете свою среду выполнения и можете быть абсолютно уверены в поддерживаемых функциях. Именно вы выбираете, какую версию программного обеспечения использовать, в зависимости от потребностей проекта и возможностей сервера.

У Node.js есть публичный график релизов, из которого видно, что нечетные версии не имеют долгосрочной поддержки. Текущая LTS-версия (long-term support) будет активно разрабатываться до апреля 2019 года, а затем поддерживаться до 31 декабря 2019 года.

В свежих версиях Node появляется много новых функций, обновлений безопасности и улучшений производительности, поэтому очень полезно использовать текущую активную версию. Тем не менее, никто не заставляет вас делать это, нет ничего плохого в том, чтобы использовать старую версию и игнорировать обновления, если они вам не нужны.

Node.js широко применяется в современном фронтенде – трудно найти проект проект, который не использует инструменты этой платформы. Скорее всего, вы уже знакомы с nvm (node version manager), который позволяет установить несколько версий Node одновременно для разных проектов. Это полезно, ведь если разные приложения используют разные релизы, было бы сложно синхронизировать и тестировать их на одной машине. Такие инструменты существуют и для многих других языков, например, virtualenv для Python, rbenv для Ruby.

Babel не нужен

Так как вы можете выбирать любую LTS-версию Node.js, то ничего не мешает использовать ту, в которой поддерживаются практически все современные возможности языка (ES 2015), за исключением хвостовой рекурсии.

Следовательно, Babel вам нужен, только если вы застряли с очень старой версией, или используете JSX-синтаксис, или хотите применять суперновые возможности, которые еще не вошли в стандарт.

Также нет необходимости в использовании webpack или browserify, и поэтому у нас нет инструмента для перезагрузки кода – вы можете использовать nodemon для перезапуска приложения после внесения изменений.

И поскольку мы никуда не отправляем написанный код, нет необходимости его минимизировать – на один шаг меньше в рабочем процессе. Вы просто используете свой код как есть! Очень непривычно.

Стиль коллбэков

Исторически сложилось так, что асинхронные функции в Node.js принимают обратные вызовы с сигнатурой (err, data) , где первый аргумент представляет ошибку. Если он равен null , то все хорошо, иначе придется что-то предпринимать. Эти обработчики вызываются после получения ответа, например, при попытке прочитать файл:

Вскоре выяснилось, что этот стиль крайне затрудняет написание читаемого и поддерживаемого кода, именно с ним связано callback hell. Позже появился асинхронный Promise – он был стандартизирован в ECMAScript 2015 (это глобальный объект как в браузере, так и в Node.js). Недавно ECMAScript 2017 ввела синтаксис async / await, доступный в Node.js 7.6+, который вы уже можете использовать.

С промисами мы избегаем «ада коллбэков», но появляется другая проблема: старый код и многие встроенные модули до сих пор используют обратные вызовы. Однако их можно преобразовать в обещания. Для примера давайте конвертируем метод fs.readFile:

Этот шаблон может быть легко расширен на любую функцию. Кроме того, существует специальный метод utils.promisify. Вот пример из официальной документации:

Разработчики Node.js понимают, что нужно переходить от старого стиля к новому, поэтому они пытаются внедрить промисифицированную версию встроенных модулей – например, уже есть промисифицированный модуль файловой системы, хотя он пока экспериментальный.

Вы все еще можете столкнуться со старым кодом с обратными вызовами. Рекомендуется обернуть его с помощью utils.promisify .

Цикл событий

Цикл событий почти такой же, как и в браузере, но с некоторыми расширениями.

Некоторые методы JavaScript позволяют извлечь код из основной очереди и выполнить его асинхронно:

Промисы, вроде Promise.resolve выполняются в той же итерации цикла обработки событий, но после остального синхронного кода.

Это специфическая для Node.js операция, которая ведет себя как microtask, но с приоритетом. Такой код будет выполняться сразу после всего синхронного кода, даже если ранее были введены другие микрозадачи. Это опасно, и может привести к бесконечным циклам. Название метода неудачно и может вводить в заблуждение, так как код выполняется во время текущей итерации, а не на следующем тике, но из-за соображений совместимости оно, вероятно, останется прежним.

Этот метод уже существует в некоторых браузерах, но еще не стандартизирован, и его следует использовать с осторожностью. Он похож на setTimeout(0) , но иногда имеет приоритет над ним. Именование здесь также не самое подходящее – мы говорим о следующей итерации цикла событий, а это не совсем immediate.

Таймеры ведут себя одинаково и в Node, и в браузере. Важно понимать, что установленная задержка не является гарантированной. Код будет выполнен по истечении времени задержки, но только после того, как основной цикл завершит все операции (включая микрозадачи) и если не будет других таймеров с более высоким приоритетом.

Давайте посмотрим на пример со всем вышеперечисленным:

Правильный вывод скрипта размещен ниже, но если хотите, попробуйте определить его самостоятельно:

Вот правильный вывод:

Вы можете узнать больше о цикле событий и методе process.nextTick в официальной документации Node.js.

Event Emitters

Многие встроенные модули Node.js создают или получают различные события. Платформа реализует EventEmitter по шаблону публикации-подписки. Это очень похоже на события в браузере, но с немного другим синтаксисом. Чтобы разобраться, проще всего реализовать все самостоятельно:

Эта реализация просто показывает принципы работы шаблона. Она не точная, не используйте ее в своем коде!

Этот код позволяет подписаться на события, отписаться от них позже позже, а также создавать. Объект ответа, объект запроса, потоки в Node – все они фактически расширяют или реализуют EventEmitter!

Эта простая концепция реализована во многих npm-пакетах: 1, 2, 3 и ряде других.

Потоки

Потоки в Node – самая лучшая и непонятная идея.

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

Этот код будет работать, особенно на локальной машине, но вы видите в нем проблему? Мы помещаем читаемый файл в память, и если он слишком велик, то это не будет работать. Это также не сработает, если у нас много параллельных запросов.

Но этот файл нам совсем не нужен – мы просто возвращаем его, даже не заглядывая внутрь. Поэтому можно прочитать какую-то его часть, немедленно отдать ее, освободить память и повторить все это снова, пока не закончим. Это упрощенное описание потоков – у нас есть механизм получения данных в чанках (кусками), и мы можем решать, что с ними делать. Например, сделаем то же самое:

Здесь мы создаем поток для чтения из файла. Этот поток реализует класс EventEmitter. По событию data мы получаем следующий чанк, а событие end сигнализирует, что поток закончился. Эта реализация работает так же, как и раньше – мы ждем, пока весь файл будет прочитан, а затем возвращаем егопользователю. Проблема сохранения данных в памяти никуда не делась.

Объект ответа сам является записываемым потоком, это значит, что мы можем отдавать ему информацию напрямую, не сохраняя ее:

Теперь нам больше не нужна переменная result , мы просто записываем уже прочитанные чанки сразу в ответ! Это означает, что можно читать даже большие файлы и не беспокоиться о параллельных запросах – память не будет исчерпана.

Осталась еще одна проблема: эти потоки имеют разные задержки. Через некоторое время поток ответа будет перегружен, так как он намного медленнее. У Node.js есть решение для этой проблемы: каждый читаемый поток имеет метод pipe, который контролирует загрузку и управляет подачей данных, приостанавливая и возобновляя ее по необходимости. Используя этот метод, можно упростить код:

Потоки в Node менялись несколько раз, поэтому будьте особенно внимательны при чтении старых руководств и всегда проверяйте официальную документацию!

Система модулей

Node.js использует модули commonjs. Каждый раз, когда вы используете require ,чтобы получить какой-то модуль внутри конфигурации webpack или когда объявляете module.exports , вы фактически применяете этот механизм. Возможно, также видели что-то вроде exports.something = <> , без слова module . Давайте разберемся, как это работает.

Прежде всего, речь пойдет о модулях commonjs с обычным расширением .js , а не о .esm / .mjs -файлах (модули ECMAScript), которые позволяют использовать синтаксис import / export . Кроме того, важно понимать, что webpack и browserify (и другие инструменты сборки) используют свою собственную функцию require , которая немного отличается.

Итак, откуда мы на самом деле получаем эти &#171;глобальные&#187; объекты module , require и exports ? Их добавляет сама платформа – вместо того, чтобы просто выполнять файл javascript, она фактически обертывает его в функцию со всеми этими переменными:

Чтобы увидеть эту оболочку, нужно выполнить следующий фрагмент кода в командной строке:

Эти переменные вводятся в модуль и доступны в нем как &#171;глобальные&#187;, хотя на самом деле таковыми не являются. Обязательно взгляните на них внутри модуля и в &#171;главном &#171;файле – можно просто вызвать console.log(module) – и сравните.

Далее рассмотрим объект exports и тонкости работы с ним:

Приведенный выше пример может озадачить вас. exports &#8212; это аргумент, передаваемый функции. Если мы присваиваем ему новый объект, то просто переписываем эту переменную, а старая ссылка исчезает. А module.exports ссылается на тот же объект:

Наконец, require – это функция, которая берет имя модуля и возвращает его объект exports . Как именно она находит модуль? Существует довольно простая последовательность действий:

  • сравнить модули ядра с указанным именем;
  • если путь начинается с ./ или. ./ , попробовать найти такой файл;
  • если файл не найден, попробовать найти каталог с таким именем с файлом index.js
  • если путь не начинается с ./ или ./ , зайти в node_modules/ и проверить наличие там папки/ файла:
  • в той директории, где запустился скрипт
  • на один уровень выше, пока не найдется /node_modules

Есть и некоторые другие места поиска, которые в основном предназначены для совместимости. Также вы можете указать свой путь для поиска с помощью переменной NODE_PATH. Если вы хотите видеть точный порядок поиска модулей, просто выведите объект модуля на консоль и найдите свойство paths . Оно выглядит примерно так:

Также важно знать, что после первого вызова require объект модуля кэшируется. При последующих вызовах система не будет его искать, а просто вернет из кэша. Это означает, что код при инициализации модуля будет выполнен только один раз. Однако можно удалить идентификатор модуля из кэша и перезагрузить его, если требуется.

Переменные окружения

Как указано в 12-factor-app, рекомендуется хранить конфигурацию в переменных среды. Можно настроить переменные для сеанса терминала:

Node – это кросс-платформенный движок, и в идеале ваше приложение должно запускаться на любой платформе. Примеры в статье охватывают только MacOS / Linux и не будут работать для Windows. Синтаксис переменных среды в Windows отличается, вы можете использовать что-то вроде cross-env, но имейте это ввиду и в других случаях.

Вы можете добавить эту строку в свой профиль bash/zsh, чтобы она была настроена в любой новой сессии.

Однако обычно вы просто запускаете приложение с этими переменными:

Доступ к ним можно получить с помощью объекта process.env:

Все вместе

В этом примере мы создадим простой http-сервер, который вернет файл с именем, указанным в URL после символа / . Если файл не существует, вернется ошибка 404 Not Found . Если пользователь попытается использовать относительный или вложенный путь, мы отправим ему ошибку 403 .

Зачем нужен Node.js – Подробное объяснение и курсы

Зачем нужен Node.js? Возрастающая популярность JavaScript повлекла за собой множество изменений, в том числе и в том, что собой представляет современная веб-разработка. Перед тем как углубиться в Node.js, вам, вероятно, будет интересно узнать о преимуществах использования JavaScript в стеке, в котором объединен язык и текстовый формат данных (JSON).

Так как это по большей части преимущество JavaScript в целом, а не Node.js, мы не будем на этом останавливаться. Тем не менее, это главный аргумент в пользу внедрения Node в ваш стек. Перед тем как мы перейдем к cамой статье, рекомендую вглянуть на один из самых лучших курсов по Node.js на сегодняшний день.

Из статьи в Википедии становится понятно, что Node.js это программный пакет, основанный на JavaScript-движке Google V8. Он включает уровень абстракции платформы – библиотеку libuv, и базовую библиотеку, которая сама главным образом написана на JavaScript. Кроме того, стоит отметить, что создатель Node.js Райан Даль намеревался создавать сайты, работающие в реальном времени с технологией push, вдохновившись такими приложениями, как Gmail. В Node.js он предоставил разработчикам инстумент для работы с парадигмой неблокирующего событийно-ориентированного ввода/вывода.

&#171;Спустя больше 20 лет существования парадигмы «веб-приложения без запоминания состояния на базе соединения запрос-отклик без запоминания состояния», у нас наконец появились веб-приложения с двунаправленными соединениями в реальном времени.&#187;

Зачем нужен Node.js

Если коротко, то Node.js блистательно себя показывает в веб-приложениях реального времени, используя технологию push в веб-сокетах. Что же здесь такого инновационного? Спустя более 20 лет существования парадигмы «веб-приложения без запоминания состояния на базе соединения запрос-отклик без запоминания состояния», у нас наконец появились веб-приложения с двунаправленными соединениями в реальном времени, в которых связь может быть инициирована клиентом или сервером, что позвляет им свободно обмениваться данными. Такой подход резко контрастирует с традиционной парадигмой веб-откликов, в которой связь всегда инициирует клиент. Кроме того, она основана на открытом веб-стеке (HTML, CSS и JS), работающем через стандартный порт 80.

Кто-то скажет: «Но ведь уже несколько лет по такому же принципу работают Flash- и Java-апплеты». В действительности они были реализованы на базе сред песочниц, в которых Веб использовался в качестве транспортного протокола для доставки клиенту. Вдобавок к этому, они работали изолированно и, чаще всего, через нестандартные порты, для которых были необходимы дополнительные права доступа и так далее.

Благодаря всем своим преимуществам Node.js играет важнейшую роль в технологическом стеке многих именитых компаний, которые широко используют его ключевые преимущества. Сообщество Node.js Foundation собрало основые доводы относительно того, почему компаниям стоит присмотреться к Node.js, и объединило их в небольшую презентацию, с которой можно ознакомиться здесь.

В этой статье я расскажу не только о том, как реализованы эти преимущества, но и о том, для чего стоит или не стоит использовать Node.js. И сделаю я это на примере некоторых классических моделей веб-приложений.

Зачем нужен Node.js &#8212; Как это работает?

Основная идея Node.js заключается в использовании неблокирующего событийно-ориентированного ввода/вывода, чтобы оставаться легковесным и эффективным при работе с приложениями, обрабатывающими большие объемы данных в реальном времени и работающими на распределенных устойствах. Звучит довольно сложно, да?

&#171;На самом деле это значит, что Node.js НЕ является универсальной платформой для любых задач, которая станет передовой на рынке веб-разработки. Совсем наоборот – это платформа для конкретных целей.&#187;

На самом деле это значит, что Node.js НЕ является универсальной платформой для любых задач, которая станет передовой на рынке веб-разработки. Совсем наоборот – это платформа для конкретных целей. И это очень важно понимать. Node.js определенно не стоит использовать для операций с интенсивной вычислительной нагрузкой на центральный процессор. Такого рода применение сведет на нет все его преимущества. Зато Node отлично себя покажет при построении быстрых масштабируемых сетевых приложений, поскольку он может одновременно обрабатывать большое количество соединений с большой пропускной способностью, что равноценно высокой масштабируемости.

То, как это работает изнутри, заслуживает особого внимания. В отличие от традиционных веб-сервисов, в которых каждое соединение (запрос) создает новый поток, используя при этом системную оперативную память и в конечном счете выжимая максимум из всего доступного объема памяти, Node.js работет на базе одного потока и использует при вызовах неблокирующий ввод/вывод, что позволяет ему поддерживать десятки тысяч одновременных соединений (хранящихся в цикле событий).

Зачем нужен Node.js

Вот, навскидку простой пример: представьте, что каждый поток может затребовать 2 Мб памяти, а объем оперативной памяти всей системы составляет 8 Гб. Теоретически максимальное количество одновременных соединений составляет 4000 (данные расчета взяты из статьи Майкла Абернети «Что именно собой представляет Node.js?», опубликованной на ресурсе IBM для разработчиков «IBM developerWorks» в 2011 году; к сожалению, статьи больше нет в свободном доступе), плюс затраты на переключение контекста между потоками. Обычно с таким сценарием приходится сталкиваться при использовании традиционных веб-сервисов. Node.js позволяет избежать всего этого и добиться уровня масштабируемости свыше миллиона одновременных соединений и свыше 600 тысяч одновременных соединений веб-сокетов.

Конечно, открытым остается вопрос распределения единственного потока между всеми клиентскими запросами, и это является одним из подводных камней при создании приложений на Node.js. Во-первых, сложные вычисления могут забить единственный поток Node, что, в свою очередь, создаст всем клиентам определенные проблемы (об этом чуть позже), поскольку входящие запросы будут заблокированы до тех пор, пока эти вычисления не будут завершены. Во-вторых, разработчикам нужно быть очень осторожными, чтобы не допустить появления исключений до базового (самого верхнего) цикла событий Node.js – это может привести к прекращению работы копии Node.js (фактически, к завершению работы всей программы).

Для избежания исключений до самой поверхности используем прием, который заключается в обратной передаче ошибок вызывающей стороне в виде параметров обратного вызова (без выбрасываний, что характерно для других сред). Даже если какие-то необработанные исключения все-таки всплывают, для отслеживания процесса Node.js и выполнения необходимого восстановления копии, которая аварийно завершилась (хотя восстановить пользовательский сеанс вряд ли удастся), были разработаны специальные инструменты. Самый распространенный из них это модуль Forever; также можно использовать внешние системные инструменты Upstart и Monit.

NPM: Менеджер пакетов Node

При разговоре о Node.js очень важно не упустить одну важную деталь. Это встроенная поддержка управления пакетами с помощью инструмента NPM, который по умолчанию идет в любой установке Node.js. Принцип модулей NPM схож с принципом Ruby Gems – это набор повторно используемых компонентов, находящихся в открытом доступе. Их можно легко установить из сетевого репозитория, с поддержкой управления версиями и зависимостями.

С полным списком пакетных модулей можно ознакомиться на сайте npm; он также доступен в CLI-инструменте npm, который автоматически устанавливается вместе с Node.js. Экосистема модулей открыта для всех, то есть любой желающий может опубликовать свой собственный модуль, который впоследствии будет размещаться в репозиторие npm. С кратким введением в npm можно ознакомиться в Руководстве для начинающих, а подробнее о том, как размещать модули здесь (информация на английском языке).

Предлагаем вашему вниманию список самых полезных модулей npm:

    (он жеjs) – это фреймворк для веб-разработки для Node.js в духе Sinatra; фактически стандартный для большинства существующих приложений Node.js.
  • hapi– очень модульный и простой в работе фреймворк, ориентированный на кофигурацию, для создания веб- и сервисных приложений – это HTTP-серверный фреймворк для js с возможностью расширения, который предоставляет коллекцию высокопроизводительных плагинов, известных под названием «межплатформенное ПО»; служит основой для Express.
  • socket.ioи sockjs – серверная часть двух самых популярных на сегодняшний день веб-сокетных компонентов.
  • pug(ранее Jade) – один из известных шаблонных движков в духе HAML; используется по умолчанию в js.
  • mongodbи mongojs – обертки MongoDB, которые предоставляют ИПП для объектных баз данных MongoDB в Node.js. – клиентская библиотека.
  • lodash (underscore, lazy.js)– своеобразный «пояс с инструментами» JavaScript. Первопроходцем была Underscore, но ее обошли две аналогичные библиотеки, в основном за счет более высокой производительности и модульной реализации. – чуть ли не самая распространенная утилита, которая обеспечивает непрерывное выполнение сценария на конкретном узле. Позволяет вашему процессу js работать бесперебойно при любых непредвиденных сбоях.
  • bluebird– полнофункциональная реализация промисов/A+ с невероятно высокой производительностью.
  • moment– легкая JavaScript-библиотека для анализа, подтверждения, обработки и форматирования дат.

Список можно продолжать очень долго. Существует еще очень много полезных пакетов, доступных каждому.

Зачем нужен Node.js &#8212; примеры использования

Чат это самое типичное многопользовательское приложение, работающее в режиме реального времени. Если раньше были ретрансплируемые интернет-чаты на базе технологии IRC (были и такие времена), использующие различные частные и открытые протоколы, работающие через нестандартные порты, то сегодня можно реализовать все на Node.js с помощью веб-сокетов, работающих через стандартный порт 80.

Чат это действительно отличный пример приложения на Node.js: это легковесное приложение с высоким трафиком, интенсивно обрабатывающее большие объемы данных (с низким потреблением вычислительных мощностей) и работающее на распределенных устройствах. Он также хорошо подходит для обучения, поскольку довольно простой, и в то же время охватывает большинство парадигм, которые вам когда-либо понадобятся в типичном приложении Node.js.

Давайте разберемся, как он работает на простом примере. Представим, что у нас на сайте есть одна комната чата, куда люди заходят и могут обмениваться сообщенияи со всеми пользователями. И, к примеру, на сайте находится три человека, которые могут писать сообщения на нашем форуме.

На стороне сервера у нас работает простое приложение Express.js, в котором реализуются две функции: 1) обработчик запросов GET ‘/’, который обслуживает веб-страницу, на которой находится форум с сообщениями и кнопка «Отправить», которая инициирует ввод нового сообщения; 2) сервер веб-сокетов, который отслеживает поступление новых сообщений, выдаваемых клиентами веб-сокетов.

На стороне клиента у нас находится HTML-страница с двумя настроенными обработчиками; один отслеживает события нажатия кнопки «Отправить», которая «подхватывает» введенное сообщение и отправляет его вниз на веб-сокет, а второй отслеживает новые входящие сообщения, поступающие клиенту веб-сокетов (то есть, сообщения, отправленные другими пользователями, которые сервер хочет отобразить с помощью этого клиента).

Зачем нужен Node.js

Как только один из клиентов отправляет сообщение, происходит следующее:

  1. Браузер «подхватывает» нажатие кнопки «Отправить» с помощью обработчика JavaScript, забирает значение из поля ввода (то есть, текст сообщения) и выдает сообщение веб-сокета с помощью клиента веб-сокетов, подключенного к нашему серверу (он инициализируется одновременно с веб-страницей).
  2. Серверный компонент веб-сокетного соединения получает сообщение и перенаправляет его на все остальные подключенные клиенты путем широковещательней передачи.
  3. Все клиенты получают новое push-сообщение с помощью веб-сокетного клиентского компонента, который работает на веб-странице. После этого они «подхватывают» содержание сообщения и локально обновляют веб-страницу, добавляя новое сообщение на форум.

Это был самый простой пример. Чтобы создать более надежное решение, можно использовать простой кэш на базе хранилища Redis. Можно пойти дальше и создать еще более продвинутое решение. Это очередь сообщений для обработки маршрутизации сообщений к клиентам и более надежный механизм доставки. Он может компенсировать временные потери соединения или хранить сообщения для зарегистрированных клиентов, пока они находятся в режиме офлайн. Независимо от того, какие улучшения вы захотите реализовать, Node.js будет по-прежнему работать согласно тем же базовым принципам: реагирование на события, обработка большого количества одновременных соединений и обеспечение плавного взаимодействия с пользователем.

ИПП ПОВЕРХ ОБЪЕКТНО-ОРИЕНТИРОВАННОЙ БАЗЫ ДАННЫХ

Хотя Node.js отлично показывает себя в приложениях, работающих в режиме реального времени, он также хорошо подходит для выдачи данных из объектных баз данных (например, из MongoDB). Данные в формате JSON позволяют Node.js работать без рассогласования интерфейсов и преобразования данных.

К примеру, если вы используете Rails, вам необходимо преобразовывать JSON в бинарные модели, а затем выдавать их обратно в виде JSON по HTTP, когда данные используются Backbone.js, Angular.js и т.п., и даже обычными вызовами jQuery AJAX. С помощью Node.js вы можете просто выдавать свои объекты JSON клиенту для использования с помощью ИПП REST. Вам также не нужно беспокоиться о преобразовании между JSON и чем-то другим при считывании или записи в свою базу данных (если вы используете MongoDB). В целом, вы сможете устранить множественные преобразования, используя стандартный формат сериализации данных на клиенте, сервере и в базе данных.

ОЧЕРЕДИ ВВОДА

Если вы одновременно получаете большие объемы данных, ваша база данных может стать узким местом. Как уже было описано выше, Node.js может легко обрабатывать одновременные соединения. Но поскольку обращение к базе данных в данном случае блокирующая операция, у нас появляются проблемы. Решением будет записать поведение клиента до того, как данные будут на самом деле записаны в базу.

При таком подходе система будет сохранять свою отзывчивость при высокой нагрузке, что в особености полезно, когда клиенту не нужно четкое подтверждение успешной записи данных. Типичные примеры: регистрация или запись данных об активности пользователей, которые обрабатываются пакетами и не используются до определенного времени; операции, которые не требуют мгновенного отображения (например, счетчик лайков на Facebook), и в которых допустима согласованность в конечном счете (которая часто используется в NoSQL).

Данные выстраиваются в очередь с помощью специальной инфраструктуры кэширования или организации очередей сообщений (например RabbitMQ, ZeroMQ) и обрабатываются в рамках процесса записи отдельных пакетов в базу данных или с помощью серверных служб по обработке, расчитанных на интенсивные вычисления и записанных для таких целей на более производительной платформе. Похожее поведение можно реализовать и с помощью других языков/фреймвороков, но на другом аппаратном оборудовании с другой высокой стабильной пропускной способностью.

Если коротко, то с помощью Node можно откладывать операции записи в базу данных и обработать их позже, продолжая работу таким образом, как будто они были выполнены.

ПОТОКОВАЯ ПЕРЕДАЧА ДАННЫХ

На более традиционных веб-платформах HTTP-запросы и отклики воспринимаются как отдельные события; на самом деле они представляют собой потоки. Это можно использовать в Node.js для создания очень полезных возможностей. Например, можно обрабатывать файлы, пока они еще загружаются. Поскольку данные поступают в виде потока, мы можем обрабатывать их в режиме онлайн. Это можно применить, к примеру, для кодирования аудио- и видеоинформации в режиме реального времени. И для установки прокси-сервера между различными источниками данных (об этом подробнее в следующем разделе).

ПРОКСИ-СЕРВЕР

Node.js можно легко использовать в качестве прокси-сервера, в котором он сможет обрабатывать большое количество одновременных соединений в режиме неблокирования. Это особенно удобно при проксировании различных сервисов с различным временем отклика, а также при сборе данных из большого количества источников.

Давайте рассмотрим такой пример. Существует серверное приложение, которое связывается со сторонними ресурсами. Оно принимает данные с различных источников или хранит такие ресурсы, как изображения и видео, и передает их на сторонние облачные сервисы.

Несмотря на то, что выделенные прокси-серверы существуют, использование вместо них Node может быть удобным. Удобным тогда, когда у вас нет прокси-инфраструктуры или если вам нужно решение для локальной разработки. Под этим я понимаю то, что вы сможете создать клиентское приложение с сервером разработки Node.js для хранения ресурсов и добавления прокси/заглушек для запросов к ИПП, в то время как в реальных условиях такие взаимодействия выполнялись бы с помощью выделенного прокси-сервера (nginx, HAProxy и т.п.).

БРОКЕРИДЖ – ИНФОРМАЦИОННАЯ ПАНЕЛЬ БИРЖЕВОГО МАКЛЕРА

Давайте вернемся на уровень приложений. Еще одним примером, в котором преобладают программы для ПК, но их можно легко заменить на веб-решения, работающие в реальном времени, это ПО для брокерского трейдинга, которое отслеживает котировки акций, выполняет вычисления и технический анализ, а также выводит графики и диаграммы.

Переход на веб-решения, работающие в реальном времени, позволит брокерам легко переключаться между рабочими станциями или рабочими местами. Вполне возможно, что в скором времени мы начнем замечать их на пляжах Флориды, Ибицы и Бали.

ПАНЕЛЬ МОНИТОРИНГА ПРИЛОЖЕНИЙ

Еще одним типичным вариантом использования, для которого отлично подходит модель Node с веб-сокетами, является слежение за посетителями сайта и отображение их взаимодействия в реальном времени.

Можно собирать статистику о пользователях в реальном времени; можно пойти еще дальше и добавить целевые воздействия со своими посетителями, открывая канал связи при достижении ими определенной точки в вашей воронке (если вас это заинтересовало, эта идея уже реализована с помощью CANDDi).

Только представьте, как вы могли бы улучшить свой бизнес, если бы знали, что делают ваши пользователи в реальном времени, если бы можно было визуализировать их взаимодействия. Теперь у вас будет такая возможность с помощью двунаправленных сокетов Node.js, работающих в реальном времени.

ПАНЕЛЬ КОНТРОЛЯ СИСТЕМЫ

Давайте теперь поговорим об инфраструктуре. Представьте, что есть SaaS-провайдер, который хочет предложить своим клиентам страницу для отслеживания сервисов (такую как статусную страницу GitHub, например). Используя цикл событий Node.js мы можем создать мощную веб-панель, которая асинхронно отслеживает статус сервисов и отправляет данные клиентам через веб-сокеты.

С помощью этой технологии можно в реальном времени передавать информацию о статусе как внутренних (корпоративных), так и общедоступных сервисов. Если развить эту идею дальше, можно довольно легко представить сетевой операционный центр, который осуществляет контроль работы приложений оператора связи, поставщика облачных сервисов, сетевых услуг и хостинга, а также финансового учреждения. Все это работает в открытом веб-стеке на базе Node.js и веб-сокетов вместо Java и/или Java-апплетов.

Примечание: Не пытайтесь создавать на базе Node системы жесткого реального времени Node (то есть системы, требующие точного времени отклика). Для такого рода приложений лучше всего использовать Erlang.

Зачем нужен Node.js &#8212; где можно использовать

Зачем нужен Node.js &#8212; СЕРВЕРНЫЕ ВЕБ-ПРИЛОЖЕНИЯ

Node.js с Express.js можно также использовать для создания классических серверных веб-приложений. И хоть это и возможно, эта парадигма запрос-отклик, в которой Node.js будет переносить отображенный HTML, не является типичным вариантом использования. Есть аргументы за и против этого подхода. Вот некоторые из них:

Преимущества:

  • Если ваше приложение не выполняет вычислений с интенсивной нагрузкой на центральный процессор, его можно полностью создать на Javascript. В том числе и базу данных, если вы используете объектную базу данных JSON, например MongoDB. Это существенно упрощает процесс разработки (в том числе подбор специалистов).
  • Поисковые модули получают в ответ полностью отображенный HTML. Он гораздо более дружественный к SEO, чем, скажем, одностраничное приложение или веб-сокетное приложение, работающее на базе js.

Недостатки:

  • Любые вычисления с интенсивной нагрузкой на центральный процесор будут блокировать отзывчивость js, поэтому лучше в таком случае использовать мнгопоточную платформу. Можно также попробовать горизонтальное масштабирование вычислений*.
  • Использование js с реляционной базой данных несет в себе много сложностей (об этом подробнее ниже). Для реляционных операций лучше всего выбрать какую-нибудь другую среду, к примеру Rails, Django или ASP.Net MVC.

* Как вариант, для таких вычислений с интенсивной нагрузкой на центральный процессор можно создать высокомасштабируемую среду на базе MQ с обработкой на стороне сервера, чтобы Node оставался спереди и асинхронно обрабатывал клиентские запросы.

Зачем нужен Node.js &#8212; где не стоит использовать

Зачем нужен Node.js &#8212; СЕРВЕРНОЕ ВЕБ-ПРИЛОЖЕНИЕ С РЕЛЯЦИОННОЙ БАЗОЙ ДАННЫХ

Если сравнивать Node.js и Express.js с Ruby on Rails с точки зрения доступа к реляционным данным, выбор будет явно в пользу последнего.

Инструменты реляционных баз данных для Node.js по-прежнему находятся на этапе доработок, поэтому работать с ними пока не очень удобно. Rails же осуществляет автоматическую настройку доступа доступа к данным «прямо из коробки». Он также предоставляет инструменты для поддержки миграций схем баз данных и другие «плюшки». Rails и соответствующие фреймворки имеют серьезные и проверенные реализации доступа к уровню данных (Active Record или Data Mapper), которых вам будет очень не хватать, если вы решите воссоздать их на чистом JavaScript.*

Но если вы действительно склоняетесь к тому, чтобы все делать исключительно на JavaScript (и готовы немного помучиться), будьте внимательны при работе с Sequelize и Node ORM2 – они пока находятся не в самом идеальном виде, но в скором времени это изменится.

* Можно использовать Node (что довольно часто практикуется) исключительно на стороне клиента, а back-end при этом реализовать на Rails, что позволит обеспечить простой доступ к реляционной базе данных.

Зачем нужен Node.js &#8212; СЛОЖНЫЕ СЕРВЕРНЫЕ ВЫЧИСЛЕНИЯ И ОБРАБОТКА

Если говорить о сложных вычислениях, Node.js не самая лучшая платформа. Вам определенно не стоит создавать на Node.js сервер вычислений Фибоначчи. В общем, любые операции с интенсивной вычислительной нагрузкой на центральный процессор сводят на нет все преимущества пропускной способности, которые предоставляет Node в рамках модели неблокирующего событийно-ориентированного ввода/вывода, поскольку любые входящие запросы будут блокироваться, пока поток занят обработкой данных.

Как было указано выше, Node.js однопоточный и использует всего лишь одно ядро процессора. Когда необходимо реализовать параллельную работу на многоядерном сервере, группа разработчиков ядра Node должна заняться подготовкой кластерного модуля. Можно также легко запустить несколько экземпляров сервера Node.js за обратным прокси-сервером через nginx.

С помощью кластеризации вы все равно сможете выгрузить все сложные вычисления в фоновые процессы, работающие в более приемлемой для этого среде, и обеспечить между ними соединение через сервер очереди сообщений, такой как RabbitMQ.

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

Конечно, такой же подход можно применить и на других платформах, но с Node.js вы сможете получить ту самую пропускную способность (количество запросов в секунду), о который мы говорили ранее, поскольку каждый запрос это маленькая задача, выполняемая очень быстро и эффективно.

Зачем нужен Node.js &#8212; Вывод

Мы рассказали все о Node.js с теоретической и практической точек зрения. Вы узнали о целях и назначениях, а также о различных «плюшках» и подводных камнях. Когда у людей возникают проблемы при работе с Node, чаще всего они сводятся к тому, что корнем зла являются блокирующие операции. В 99% случаев причина всех проблем заключается в неправильном использовании Node.

&#171;При работе с Node корнем зла являются блокирующие операции. В 99% случаев причина всех проблем заключается в неправильном использовании Node.&#187;

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *