Pull to refresh

Node.js на Windows (с тестами производительности)

Reading time 11 min
Views 48K


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

Node.js — это событийно-ориентированный фреймворк на языке Javascript для создания сетевых приложений. Основная идея в том, что в ходе выполнения кода ничто не блокируется — отсутствуют операции, которые что-то ждут, например передачи данных, ввода пользователя или установки соединения. Все построено на событиях, которые происходят в момент наступления того, чего синхронные операции дожидаются. Это дает значительное, иногда в десятки раз, преимущество в производительности по сравнению со старыми синхронными системами. С версии 0.6.0, которая вышла в ноябре 2011-го года, сборка Node.js для Windows объявлена стабильной.


Устанавливаем рабочее окружение



Для начала необходимо скачать и установить Web Platform Installer, запустить его, кликнуть на «Options» и в поле “Display additional scenarios” добавить ссылку на Helicon Zoo Feed: http://www.helicontech.com/zoo/feed/




После этого в Web Platform Installer появится закладка Zoo:





Установка Node.js



На вкладке Zoo —> Engines есть список всех доступных веб движков, среди них и Node.js. Однако мы рекомендуем устанавливать пакет Node.js в который кроме самой ноды входит еще несколько полезных модулей, так что Zoo —> Packages —> Node.js Hosting Package и нажимаем Add, Install.



Увидеть все доступные на данный момент веб фреймворки и приложения можно в галлерее Helicon Zoo. После того, как вы согласитесь с лицензионными соглашениями, начнётся загрузка и установка IIS (если ещё не установлен), Helicon Zoo Module, а также самого node.exe для Windows.

Важным компонентом системы является менеджер пакетов Node Package Manager (npm), который понадобится вам для установки дополнительных модулей. К сожалению текущая версия npm на Windows работает нестабильно. Зато есть его аналог — утилита ryppi.py, которая может быть использована так же как npm. ryppi.py написан на языке Python, так что установка Node.js Hosting Package потянет за собой и питон. В будущем, если npm будет стабильно работать на Windows, мы заменим им ryppi.py, что позволит сэкономить 80мб дискового пространства на установке питона.



Установка шаблонов WebMatrix



Итак, мы установили Node.js, теперь чтобы начать писать под него приложения можно воспользоваться шаблонами для WebMatrix. Эти шаблоны позволяют создать пустые приложения-заготовки, которые можно использовать для дальнейшей разработки.
Для их установки выберем Zoo —> Packages —> WebMatrix Templates.



Если WebMatrix у вас не установлен — не беда, он будет скачан и установлен автоматически во время установки шаблонов к нему. После установки запустим WebMatrix и на главной выберем Site from Template:



Как видно на скриншоте Node.js — не единственный фреймворк, для которого доступны шаблоны WebMatrix.

После создания Node.js Site, если перейти по указанному URL или нажать «Run», вы увидите простой «Hello, World!».



По умолчанию вновь созданный сайт содержит фреймворк express, для более простого создания веб-приложений. Он сам и его зависимости находятся в директории node_modules под сайтом, что будет удобно для развертывания приложения на удаленном сервере.

Директория public предназначена для хранения статических файлов. Любой файл, помещенный в эту директорию, будет обработан непосредственно IIS как статический файл, не приводя к вызову Node.js. Это особенно важно чтобы избежать случайного запуска клиентских *.js файлов на сервере.

Файл web.config содержит в частности URL Rewrite правила для статических файлов. Вначале любой запрос проверяется на наличие такого статического файла в директории public. Это нужно для некоторых веб приложений, которые любят смешивать статические и динамические ресурсы в одной директории, чаще корневой. Если ваше приложение не подвержено этой, однозначно порочной практике, то удалите правила для Microsoft URL Rewrite из файла web.config и ссылайтесь на статические файлы, указывая директорию public явно.

А еще в файле web.config содержатся конфигурационные директивы необходимые для запуска Node.js и Helicon Zoo Module на этом сайте.



Пишем первое приложение



Одна из прелестей Node.js в том, что JavaScript — известный язык, который широко используется в веб разработке. Это значит, что у вас не возникнет проблем с выбором редактора. В нашем случае бесплатный WebMatrix вполне подойдет для начала.

Для демонстрации возможностей асинхронных веб фреймворков обычно первым делом пишут чат. Так самое известное демо-приложение на Node.js — это чат на http://chat.nodejs.org/, его исходные коды доступны для изучения.

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

Для работы будем использовать созданный нами ранее Node.js Site. Нужно будет отредактировать файлы server.js и index.html.



Вот исходные коды файла server.js:


var express = require('express');
var callbacks = [];

// Функция рассылки сообщений клиентам
function appendMessage(message){
  var resp = {messages: [message]};
  while (callbacks.length > 0) {
    callbacks.shift()(resp);
  }
}

// Создание сервера на express
var app = module.exports = express.createServer();
app.use(express.bodyParser());

// Просто вернуть index.html
app.get('/', function(req, res){
    res.sendfile('index.html');
});

// Обрабатывает сообщения от клиента
app.post('/send', function(req, res){
  var message = {
    nickname: req.param('nickname', 'Anonymous'),
    text: req.param('text', '')
  };
  appendMessage(message);
  res.json({status: 'ok'});
});

// Ждет новых сообщений
app.get('/recv', function(req, res){
  callbacks.push(function(message){
    res.json(message);
  });
});

// Слушать порт
app.listen(process.env.PORT);

и index.html

<html>
<head>
<title>Node.js Zoo Chat</title>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.6/jquery.min.js" type="text/javascript"></script>
<script type="text/javascript">

// Инициализируем после загрузки страницы
$(document).ready(function(){
  $('form#send').submit(onSend);
  longPoll();
  $('#nickname').focus();
});

// По нажатию Submit отсылает сообщение на сервер
function onSend(eventData){
  eventData.preventDefault();
  var msgArr = $(this).serializeArray();
  var message = {
    nickname : msgArr[0].value,
    text : msgArr[1].value
  };
  $.post('/send', message, function (data){
    $('#text').val('').focus();
  },
  'json');
}

// Вызывается при поступлении новых сообщений
function longPoll(data){
  if (data && data.messages) {
    for (var i = 0; i < data.messages.length; i++) {
      var message = data.messages[i];
      $('<p><b>'+message.nickname+':</b><span>'+message.text+'</span></p>').hide().prependTo('#messages').slideDown();
    }
  }
  
  // сообщение обработано, ждем следующих
  $.ajax({
    cache: false,
    type: "GET",
    url: "/recv",
    success: function(data){
       longPoll(data);
    }
  });
}
</script>
</head>
<body>
<h1>Node.js Zoo Chat</h1>
<form action="/send" method="post" id="send">
    <label for="nickname">Nickname:</label> <input name="nickname" size="10" id="nickname" />
    <label for="text">Message:</label> <input name="text" size="40" id="text" />
    <input type="submit">
</form>
<div id="messages"></div>
</body>
</html>

Для вступления изменений в силу нужно нажать Restart и затем Run:



Теперь можно убедится что чат работает, запустив его в двух разных браузерах:





Установка модулей



Для любого веб фреймворка возможно самой важной характеристикой является доступность различных модулей и использование сторонних технологий. В текущей реализации менеджер пакетов Node (Node PackageManager) под Windows работает нестабильно, хотя поддержка Windows уже заявлена и в скором будущем ситуация может измениться. На данный момент можно пользоваться менеджером пакетов написанным на Python — ryppi.py. Тут нужно помнить одну тонкость — ryppi.py всегда устанавливает модули в директорию node_modules текущей директории, где он вызван. Т.е. чтобы поставить модуль под сайт нужно зайти в директорию сайта и вызвать там команду:

C:\>cd "C:\My Web Sites\Node.js Site"

C:\My Web Sites\Node.js Site>ryppi.py install mongodb
Installing http://registry.npmjs.org/mongodb/-/mongodb-0.9.7-0.tgz into .\node_modules\mongodb ...
Checking dependencies for mongodb ...
All done.

Еще следует отметить, что не все из существующих модулей работают под Windows. Так, например великолепная, на мой взгляд, библиотека node-sync, написная кстати хабровчанином octave, под Windows работать не будет. Библиотека позволяет во многих случаях избавится от громоздкой парадигмы коллбеков, не теряя при этом асинхронной природы Node, однако базируется она на реализации node-fibers, которая под Windows не портирована. Надеюсь, что в будущем поддержка волокон (fibers) будет встроена в Node.js напрямую.
И все же большинство модулей будет стабильно работать на Windows.



CoffeScript



Если вы возьметесь писать на Node.js более-менее крупный проект, рано или поздно вы столкнетесь с тем фактом, что JavaScript — язык не слишком дружелюбный. Рой из фигурных скобочек, масса ненужных конструкций — все это не добавляет программе читабельности и усложняет дальнейшую работу над кодом. К счастью вы не первый кто с этим столкнется и проблема уже возможно решена. Так существует множество производных языков, базирующихся на JavaScript или расширяющих его. Вот, например небольшой список для ознакомления: http://altjs.org/

Можно взять CoffeeScript, как самый популярный на данный момент. Код написанный на CoffeeScript проще и его удобнее читать. Затем этот код компилируется в обычный JavaScript и исполняется. А код на JavaScript наоборот можно сконвертировать в CoffeeScript. Например скрипт server.js из нашего чата на языке CoffeeScript выглядит так:

express = require("express")
callbacks = []

// Функция рассылки сообщений клиентам
appendMessage = (message) ->
  resp = messages: [ message ]
  callbacks.shift() resp  while callbacks.length > 0

// Создание сервера на express
app = module.exports = express.createServer()
app.use express.bodyParser()


// Просто вернуть index.html
app.get "/", (req, res) ->
  res.sendfile "index.html"

// Обрабатывает сообщения от клиента
app.post "/send", (req, res) ->
  message =
    nickname: req.param("nickname", "Anonymous")
    text: req.param("text", "")

  appendMessage message
  res.json status: "ok"

// Ждет новых сообщений
app.get "/recv", (req, res) ->
  callbacks.push (message) ->
    res.json message

// Слушать порт
app.listen process.env.PORT

Узнать больше о CoffeeScript: http://jashkenas.github.com/coffee-script/(англ.)
Установить CoffeeScript: rippy.py install coffe-script



Отладка Node.js-приложений



Для отладки приложений на Node.js есть хороший инструмент — node-inspector. Он уже включён в директорию node_modules, которая есть в шаблоне Node.js-сайта. node-inspector работает так:
  • приложение, которое нужно отлаживать, запускается в debug-режиме (вызов node.exe с параметром --debug или --debug-brk);
  • запускается node-inspector, который по сути тоже есть веб-приложение;
  • по WebSocket-протоколу эти два приложения общаются между собой для передачи отладочных данных;
  • в браузере открывается страница с отлаживаемым приложением;
  • в webkit-совместимом браузере открывается интерфейс node-inspector с отладочной информацией, его интерфейс аналогичен Web Inspector в Google Chrome или Safari.

В корневой директории node.js-сайта из шаблона есть файл start_debug.cmd, который запускает отладку для текущего приложения и открывает страницы в браузере для отладки.



Отладчик в браузере выглядит так:



Развертывание на сервере



Итак, мы написали веб приложение и теперь хотим выложить его в сети. Для этого нам нужен сервер, и теперь нет ничего проще, чем настроить Windows сервер для работы с Node.js. Нам лишь понадобиться повторить несколько шагов из начала статьи, которые мы делали для развертывания рабочего окружения. А именно: поставить Microsoft Web Platform Installer, добавить в него Helicon Zoo feed и установить Node.js Hosting Package из репозитория Zoo. Все — сервер готов принять наше приложение. Из серверных платформ поддерживаются Windows 2008 и 2008 R2, 32 и 64 битные версии.

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

Helicon Zoo Module изначально разрабатывался с расчетом конфигурирования хостинг решений. Так все приложения под ним разделены и не пересекаются. Сам модуль с настройками по умолчанию работает в автоматическом режиме, создавая один воркер (процесс-обработчик), когда нагрузка мала или добавляя воркеров вплоть до числа ядер, чтобы дать максимальную производительность, если нагрузка на приложение возрастает.

В Helicon Zoo используется концепция движков (engines) и приложений (applications). Так в движках определяется, что запускать и как, по какому протоколу и на каком порту, сколько минимально и максимально воркеров разрешено и подобные глобальные настройки, которые задаются глобально в файле applicationHost.config. Затем уже под сайтом можно создать приложение, использующее конкретный движок и передать ему необходимые параметры для работы этого приложения. Это позволяет отделить работу администратора хостинга от клиентов, а клиентов друг от друга.



Тесты производительности Node.js



Тестовая машина в качестве сервера — Core 2 Quad 2.4 Ghz, 8 Gb RAM, гигабитная сеть. Для генерации нагрузки использовался более мощный компьютер и Apache Benchmark командой «ab.exe -n 100000 -c 100 –k». Для тестирования Apache и Nginx использовалась Ubuntu 11.04 Server x64. IIS 7 тесты работали на Windows Server 2008 R2. Никаких виртуалок — честное железо.

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

Вот результаты (величина на графиках — запросы в секунду):



Впечатляет, не правда ли? Теперь немного объяснений, что же меряют эти тесты. Называть их тестами производительности возможно не совсем верно, мы ведь не разные процессоры меряем. У процессора может быть производительность, а у веб серверов скорее обратный результат — сколько процессорного времени они потратили на каждый запрос.

Так в первом тесте меряются чистые накладные расходы на обработку запроса каждым конкретным веб сервером и их способность использовать ресурсы процессора. Быстрее данная связка технологий на этом процессоре вернуть ответ просто не в состоянии. В этом тесте сильно отстал Nginx на Windows потому что в этой системе Nginx открывает новое соединение с бекэндом на каждом запросе. А вот Apache на Windows наоборот порадовал пулингом соединений и настоящими потоками.

Второй и третий тесты показывают, как меняется доля накладных расходов веб сервера на обработку запроса при увеличении «веса» запроса. Однако на них теперь оказывает большее влияние множество других факторов, как то производительность файловой системы, драйверов базы данных и самой базы. Для эксперимента мы протестировали также связку Windows + Zoo + MongoDB, просто чтобы посмотреть разницу с Mongo. Ее результаты – 6793 з/с на чтение и 2906 з/с на запись. Впечатляет, особенно скорость записи.

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


По просьбам читателей выкладываем подробные графики ab. Повторно измерили только первый тест, там где простой вывод времени, потому что на нем лучше всего видно накладные расходы самого веб сервера. Конфигурационные файлы и тестируемые js скрипты можно взять тут. Там только инклуды, все остальное по умолчанию. Горизонтальная шкала — запросы, вертикальная — время ответа в милисекундах.

Windows, IIS7 + Zoo, «вывод времени»:


Ubuntu, Apache, «вывод времени»:


Ubuntu, Nginx, «вывод времени»:




Выводы



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

Скоро мы планируем добавить поддержку Erlang и Java в Helicon Zoo. Будет интересно сравнить по производительности еще эти технологии. Пока же Node.js явный лидер по скорости среди поддерживаемых веб фреймворков.

PS: Отдельная благодарность rukeba и XaocCPS за помощь в публикации этой статьи.
Tags:
Hubs:
+63
Comments 72
Comments Comments 72

Articles