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>';
Результат:
Несмотря на то, что Node.js не стремится занять место других языков программирования, он уже показал себя как многообещающая технология. Говоря про серверные решения на основе web-sockets для web и mobile-application, Node.js уверено защищает свои позиции.
Комментарии (29)
gorodnev
12.01.2017 10:35+4Никак не пойму эти попытки продвинуть node.js и выдать обертку над libev (которая в свою очередь обертка над демультиплексирующими системными вызовами вроде epoll в Linux) за революцию. Чем это принципиально отличается, например, от python gevent/twisted/etc? Складывается мнение, что у этих людей отсутствует системное мышление или их представления о мире ограничены JavaScript'ом. Ведь по сути, NodeJS — это libev + интерпретатор языка (v8 по дефолту).
Fedoskin
12.01.2017 12:20-1Спасибо за комментарий. У каждой tool есть своя задача, нет смысла сравнивать Python и Node.js. Вот например если бы вам необходимо было разработать продукт с трёхмерной графикой или со сложными математическими расчётами или проект-паук, врядли бы вы рассматривали Node.js, но если вам бы понадобилось сделать чат или какой-то продукт c активно меняющимся динамическим контентом, скорее всего вы бы посмотрели на Node.js и это логично и правильно, ведь не правильно отпираться от того факта что Node.js — технология стабильная, популярная и хорошо документированная, в отличии от EPOLL. Что касается V8 — спасибо ему за Node.js
AndreyRubankov
12.01.2017 16:09У каждой tool есть своя задача, нет смысла сравнивать Python и Node.js.
Если так, зачем Вы тогда сравнивали PHP и NodeJs?Fedoskin
12.01.2017 16:31Моя цель была показать что на PHP или любом другом серверном языке программирования свет клином не сходится и есть хорошая альтернатива которую можно попробывать и использовать по надобности и по назначению
AndreyRubankov
12.01.2017 17:46Читая статью у меня сложилось мнение, что Вы пытаетесь показать, что PHP — отстой, а NodeJS — это то, что следует использовать. Особенно учитывая то сравнение, где NodeJs невероятным образом рвет PHP по производительности.
К слову о тесте, у меня есть ощущение, что тестируется какая-то фигня, просто не верится, что разница на столько велика. А описания что делает тест (что замеряет и как с примерами исходников) Вы не предоставили. Просто красивые графики с потолка.
ps: если вы в тесет отдавали статику (что-угодно без CPU вычислений), то тест вообще ни о чем не говорит.Fedoskin
12.01.2017 18:14-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>';
oxidmod
12.01.2017 18:18зачем же вы запустили пыху под апачем? пустите под nginx))
gorodnev
12.01.2017 18:49Как зачем? Для драмы! Опять же, запуская под nginx мы получим тот же node, вид сбоку, с той же событийной архитектурой без бешеного context switching, который мы видим с Apache. Т.е. дело даже не в инструменте, а в умении его готовить.
AndreyRubankov
12.01.2017 19:56Еще интересный вопрос: Сервер (apache+php / nodejs) и Тул для нагрузочного тестирования (jmeter?) у вас были запущены на одной физической машине?
Fedoskin
12.01.2017 20:46да
AndreyRubankov
12.01.2017 23:21Это, скорее всего, основная причина столь столь низких показателей связки apache+php.
Тул для нагрузочного тестирования (далее просто Тул) создает множество потоков для эмуляции независимых пользователей. При количестве потоков более 200, большая часть ресурсов идет на обеспечение работы Тула. Планировщик потоков в ОС начинает сходить с ума.
Добавим к этому тот факт, что и у apache, и у php-fpm есть свои пулы потоков, по 1 потоку на каждого клиента. В результате вся нагрузка приходится на планировщик потоков.
В этой ситуации nodejs, у которого всего несколько потоков, будет показывать результаты лучше только потому, что во всей системе стало примерно в 3 раза меньше активных потоков.
И тут дело не в том, что nodejs крутая, тут дело в том, что сам эксперимент не является чистым; работа тестирующего тула вносит большую нелинейную погрешность в обоих случаях.
К тому же сам код для эксперимента был подобран не лучшим образом. В обоих случаях отдается статика, которая вообще никакой нагрузки не несет.
Учитывая эти факты, весь эксперимент замеряет ничто иное как работу планировщика потоков, при этом все потоки гоняются в холостую (ни один поток не выполняет полезной работы).
Тут и без замеров будет ясно, что nodejs будет показывать ошеломительные результаты.
К слову, если взять nginx и через него отдавать эту статику из кеша, результат будет еще лучше, чем у nodejs.
Source
12.01.2017 23:46К слову о тесте, у меня есть ощущение, что тестируется какая-то фигня, просто не верится, что разница на столько велика.
Apache c дефолтными настройками никогда и не был тортом для больших нагрузок. Сравнение то идёт скорее с ним, а не с PHP. Спрячь ноду за тот же самый Apache и будет такая же скорость.
Carzil
12.01.2017 16:24+1Node.js — технология стабильная, популярная и хорошо документированная, в отличии от EPOLL
epoll тоже стабилен, популярен и достаточно хорошо документирован. Но сравнивать epoll и node.js — это как сравнивать груши с галошами.
victorburre
12.01.2017 11:19+11А кому и зачем этот реферат?
Fedoskin
12.01.2017 12:27-5Спасибо за комментарий. Я указывал что публикация носит характер «tutorial» и могла бы быть полезна для тех кто ищет для себя технологию или решает что лучше использовать или просто подчеркнуть для себя чтто новое, так же можно поиграть с теми пару строчек кода которые имеются в публикации, они 100% рабочие.
victorburre
12.01.2017 12:43+7Это ни разу не туториал, он ничему не учит. Это более чем поверхностный обзор. Если бы вы потрудились выполнить поиск по существующим на Хабре публикациям, то увидели бы, что тут есть масса и более полезной информации на тему Node.js.
Fedoskin
12.01.2017 13:02-3Node.js технология популярная, конечно может быть очень много различной информации по ней, я ещё поработаю над свой публикацией и добавлю туда что-нибудь действительно интересное из практики. Спасибо за честную оценку. С удовольствием почитаю ваши публикации.
antstar
12.01.2017 14:33+2Данная публикация не несет никакой новой информации. Все уже есть либо здесь, на хабре, либо на доступных ресурсах в интернете.
Fedoskin
12.01.2017 16:42-2простите, но это очень условно, информацию ищут и не для всех всё прозрачно и понятно, а по поводу что-то где-то найти, можно и man читать и интернет не нужен, спасибо
oxidmod
http://iwf1.com/apache-vs-nginx-vs-node-js-and-what-it-means-about-the-performance-of-wordpress-vs-ghost/
Fedoskin
Спасибо за комментарий. В целом в этой статье так же говорится что Node.js объективно превосходит PHP по производительности и даже в связке с Nginx, автор:
и сам автор с пониманием говорит что Node.js — качественный продукт: Конечно можно найти много плюсов и минусов у Node.js, главное использовать его по назначению. В своей публикации, опираясь на собственный опыт, я хотел донести мысль о том что Node.js имеет место быть и способен справиться как с тривиальными так и высоконагруженными задачами и помочь разработчику разгрузить основной сервер. Надеюсь на понимание.oxidmod
на самом деле нода очень быстрая на хелоу-вордах, но вся её скорость тает как только у нас появлябтся блокирующие IO, а они будут рано или поздно в любом проекте
TimsTims
Принцип разработки ноды — не использовать блокирующие IO. А места, где они всё-же требуются — выносить за ноду в том или ином виде (микросервис, другая мини-нода под чисто-эту-задачу, итд)
Fedoskin
согласен, полноценной многопоточности у Node.js нет