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

image

Web-программирование стремительно развивается и появляется необходимость выбора между сформировавшимися языками такими как PERL, C++ и Java и современными веб-ориентированными или прототипно-ориентироваными языками как например Ruby или Go. Один из таких языков является JavaScript. Много лет присутствовало мнение что JavaScript это клиентоориентированный язык программирования и будущего у него нет, но после того как компания Google выпустила стабильную версию JavaScript-движка V8 появился Node.js и его стали использовать как совершенно новой идеи, серверного JavaScript.

Node.js продолжает развиваться динамически и амбициозно. Так например, в течении нескольких последних лет разработчиками было добавлено около 200 000 модулей для Node.js, это превышает в несколько раз темпы развития уже устоявшихся серверных языков, таких как Perl у которого количество модулей в репозитории меньше. Так же нужно подчеркнуть что технология Node.js набирает обороты и используется такими компаниями, как Yahoo, Microsoft, PayPal и LinkedIn не говоря уже про гугл.

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

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



Для построения собственных решений могут применяться уже готовые модули, которые просто адаптируются к конкретному проекту. Так например одним из самых распространенных Web application framework является “Express”, база данных может использоваться как реляционная (MySql) так и нереляционная (MongoDB), так же можно использовать различные модули для варификации и форматирования данных.

Установка Node.js и NPM под Linux (Ubuntu 16.04):

sudo apt-get install nodejs
sudo apt-get install npm

Установка библиотек WS, FS, Mysql и MongoDB из NPM:

npm install ws  //установка веб-сокет модуль
npm install fs //установка модуля для работы с файловой системой
npm install mysql // установка mysql модуля
npm install –g mongodb //установка mongodb модуля глобально

Пример установки соединения с базой данных:

var url = 'mongodb://127.0.0.1:27017';
var db = '/your_collection';

// init DB
var MongoClient = require('mongodb').MongoClient;
// connect with mongo
MongoClient.connect(url + db, function (err, mongoclient) {
     if (err) {throw err}
     var db_object = mongoclient.collection('collection');
     db_object.find({_id:some_id});
});

Для запуска nodejs скрипта нужно вызвать команду находясь в той же директории где вы устанавливали npm пакеты, т.е. на одном уровне с папкой «node_modules»:

nodejs путь_к_файлу/имя_файла.js

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

Так же есть ряд дополнительных инструментов для комфортной работы с Node.js. Так например для поддержания процессов используют утилиты: forever или supervisor. Первая устанавливается из менеджера пакетов NPM и служит только для поддержания процессов Node.js, в то время как второй умеет работать и с другими утилитами такими как RabbitMQ, Bash Scripts и тем самым является более универсальной. Так же существует модуль supervisor который устанавливается как пакет для Node.js и играет роль наблюдателя за изменениями в скрипте и автоматического перезапуска без утечки памяти ОЗУ и без очистки межмодульных зависимостей.

Установка Supervisor:

sudo apt-get install supervisor

Файл конфигурации supervisor находится в директории: /etc/supervisor/

Для включения доступа через web-интерфейс нужно добавить в файл /etc/supervisor/supervisord.conf:

[inet_http_server]
port=*:9001
username=логин
password=пароль

Для проекта необходимо создать файл конфигурации запуска node.js скрипта в директории:
/etc/supervisor/conf.d/файл.conf:

[program:имя_проекта]
directory=/путь/к/проекту
command=nodejs путь_к_файлу/имя_файла.js
autostart=true
autorestart=true
stderr_logfile=/var/log/supervisor/имя_файла.err.log
stdout_logfile=/var/log/supervisor/имя_файла.out.log

Так же Node.js имеет ряд модулей для логгирования, самые популярные (log4j, winston, bunyan, intel). Они позволяют логгировать как сценарий приложения так и непосредственно системные сообщения (ERROR, WARN, INFO, DEBUG, TRACE). Для возврата ошибок в функции может быть реализован синхронный подход (throw) или асинхронный подход (callback-функция или событие), но нельзя реализовывать оба подхода в одной функции. При использовании функции, чтобы обрабатывать возникающие в ней ошибки, нужно будет применять либо callback-функции, либо конструкцию try/catch.

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

Пример работы асинхронного чтения файла (без ожидания):

var fs = require('fs');
fs.readFile('путь', 'utf8', function(err, data) {
  console.log(data);
});
console.log('after readFile');

Пример работы синхронного чтения файла (с ожиданием):

var fs = require('fs');
var data = fs.readFileSync('путь', 'utf8');
console.log(data);

Приведём простейший тест на вывод «Hello World» и посмотрим утилитой dstat какие показатели мы получим:
nodejs:
var sys = require('sys'),
    http = require('http');
http.createServer(function(req, res){
    res.writeHead(200, {'Content-Type': 'text/html'});
    res.write('<p>Hello World</p>');
    res.end();
}).listen(8080);

php:
<?php
echo '<p>Hello World</p>';

Результат:
image

image

image

Несмотря на то, что Node.js не стремится занять место других языков программирования, он уже показал себя как многообещающая технология. Говоря про серверные решения на основе web-sockets для web и mobile-application, Node.js уверено защищает свои позиции.

Комментарии 29

      0
      Спасибо за комментарий. В целом в этой статье так же говорится что Node.js объективно превосходит PHP по производительности и даже в связке с Nginx, автор:
      which is quite surprising as a matter of fact, Node.js can be faster than Nginx and Apache in some cases
      и сам автор с пониманием говорит что Node.js — качественный продукт:
      Since there are plenty of comparisons out there explaining and demonstrating Node.js raw speed over PHP (including PHP 7) I shall not elaborate further on the subject, Google it, I implore you.
      Конечно можно найти много плюсов и минусов у Node.js, главное использовать его по назначению. В своей публикации, опираясь на собственный опыт, я хотел донести мысль о том что Node.js имеет место быть и способен справиться как с тривиальными так и высоконагруженными задачами и помочь разработчику разгрузить основной сервер. Надеюсь на понимание.
        –3

        на самом деле нода очень быстрая на хелоу-вордах, но вся её скорость тает как только у нас появлябтся блокирующие IO, а они будут рано или поздно в любом проекте

          +4
          Принцип разработки ноды — не использовать блокирующие IO. А места, где они всё-же требуются — выносить за ноду в том или ином виде (микросервис, другая мини-нода под чисто-эту-задачу, итд)
            –2
            согласен, полноценной многопоточности у Node.js нет
      +4

      Никак не пойму эти попытки продвинуть node.js и выдать обертку над libev (которая в свою очередь обертка над демультиплексирующими системными вызовами вроде epoll в Linux) за революцию. Чем это принципиально отличается, например, от python gevent/twisted/etc? Складывается мнение, что у этих людей отсутствует системное мышление или их представления о мире ограничены JavaScript'ом. Ведь по сути, NodeJS — это libev + интерпретатор языка (v8 по дефолту).

        +2
        Python + twisted — это более сложное решение, нежели Node.js. Зачем усложнять, если можно жить проще?
          0
          100% согласен
          –1
          Спасибо за комментарий. У каждой tool есть своя задача, нет смысла сравнивать Python и Node.js. Вот например если бы вам необходимо было разработать продукт с трёхмерной графикой или со сложными математическими расчётами или проект-паук, врядли бы вы рассматривали Node.js, но если вам бы понадобилось сделать чат или какой-то продукт c активно меняющимся динамическим контентом, скорее всего вы бы посмотрели на Node.js и это логично и правильно, ведь не правильно отпираться от того факта что Node.js — технология стабильная, популярная и хорошо документированная, в отличии от EPOLL. Что касается V8 — спасибо ему за Node.js
            0
            У каждой tool есть своя задача, нет смысла сравнивать Python и Node.js.

            Если так, зачем Вы тогда сравнивали PHP и NodeJs?
              0
              Моя цель была показать что на PHP или любом другом серверном языке программирования свет клином не сходится и есть хорошая альтернатива которую можно попробывать и использовать по надобности и по назначению
                0
                Читая статью у меня сложилось мнение, что Вы пытаетесь показать, что PHP — отстой, а NodeJS — это то, что следует использовать. Особенно учитывая то сравнение, где NodeJs невероятным образом рвет PHP по производительности.

                К слову о тесте, у меня есть ощущение, что тестируется какая-то фигня, просто не верится, что разница на столько велика. А описания что делает тест (что замеряет и как с примерами исходников) Вы не предоставили. Просто красивые графики с потолка.

                ps: если вы в тесет отдавали статику (что-угодно без CPU вычислений), то тест вообще ни о чем не говорит.
                  –1
                  Не в коем случае, я сам PHP разработчик с опытом и никак не хочу сказать что PHP — это «отстой»
                  Что касается тестов скрипты были просты:
                  nodejs:
                  var sys = require('sys'),
                      http = require('http');
                  http.createServer(function(req, res){
                      res.writeHead(200, {'Content-Type': 'text/html'});
                      res.write('<p>Hello World</p>');
                      res.end();
                  }).listen(8080);
                  

                  php:
                  <?php
                  echo '<p>Hello World</p>';
                  
                    0

                    зачем же вы запустили пыху под апачем? пустите под nginx))

                      0
                      Как зачем? Для драмы! Опять же, запуская под nginx мы получим тот же node, вид сбоку, с той же событийной архитектурой без бешеного context switching, который мы видим с Apache. Т.е. дело даже не в инструменте, а в умении его готовить.
                      0
                      Еще интересный вопрос: Сервер (apache+php / nodejs) и Тул для нагрузочного тестирования (jmeter?) у вас были запущены на одной физической машине?
                        0
                        да
                          0
                          Это, скорее всего, основная причина столь столь низких показателей связки apache+php.

                          Тул для нагрузочного тестирования (далее просто Тул) создает множество потоков для эмуляции независимых пользователей. При количестве потоков более 200, большая часть ресурсов идет на обеспечение работы Тула. Планировщик потоков в ОС начинает сходить с ума.

                          Добавим к этому тот факт, что и у apache, и у php-fpm есть свои пулы потоков, по 1 потоку на каждого клиента. В результате вся нагрузка приходится на планировщик потоков.

                          В этой ситуации nodejs, у которого всего несколько потоков, будет показывать результаты лучше только потому, что во всей системе стало примерно в 3 раза меньше активных потоков.

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

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

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

                          Тут и без замеров будет ясно, что nodejs будет показывать ошеломительные результаты.
                          К слову, если взять nginx и через него отдавать эту статику из кеша, результат будет еще лучше, чем у nodejs.
                      0
                      К слову о тесте, у меня есть ощущение, что тестируется какая-то фигня, просто не верится, что разница на столько велика.

                      Apache c дефолтными настройками никогда и не был тортом для больших нагрузок. Сравнение то идёт скорее с ним, а не с PHP. Спрячь ноду за тот же самый Apache и будет такая же скорость.

                  +1
                  Node.js — технология стабильная, популярная и хорошо документированная, в отличии от EPOLL

                  epoll тоже стабилен, популярен и достаточно хорошо документирован. Но сравнивать epoll и node.js — это как сравнивать груши с галошами.
                    –1
                    да, я уже писал об этом в комментариях выше
                  –2
                  javascript привлекает сонмы нубов.
                    +1
                    Думаю это стереотип, JS обрастая фреймворками стал сложноват для «нубов»
                  +11
                  А кому и зачем этот реферат?
                    –5
                    Спасибо за комментарий. Я указывал что публикация носит характер «tutorial» и могла бы быть полезна для тех кто ищет для себя технологию или решает что лучше использовать или просто подчеркнуть для себя чтто новое, так же можно поиграть с теми пару строчек кода которые имеются в публикации, они 100% рабочие.
                      +7
                      Это ни разу не туториал, он ничему не учит. Это более чем поверхностный обзор. Если бы вы потрудились выполнить поиск по существующим на Хабре публикациям, то увидели бы, что тут есть масса и более полезной информации на тему Node.js.
                        –3
                        Node.js технология популярная, конечно может быть очень много различной информации по ней, я ещё поработаю над свой публикацией и добавлю туда что-нибудь действительно интересное из практики. Спасибо за честную оценку. С удовольствием почитаю ваши публикации.
                          +2
                          Данная публикация не несет никакой новой информации. Все уже есть либо здесь, на хабре, либо на доступных ресурсах в интернете.
                            –2
                            простите, но это очень условно, информацию ищут и не для всех всё прозрачно и понятно, а по поводу что-то где-то найти, можно и man читать и интернет не нужен, спасибо

                  Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                  Самое читаемое