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



    В этой статье мы рассмотрим вопросы наиболее важные для начинающих веб программистов и тех кто задумывается об изучении 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 за помощь в публикации этой статьи.
    Share post

    Comments 72

      –7
      Мне кажется, что как-то много приложений для установки окружения. Зачем это там IIS ставить, Zoo какой-то… мне кажется в конце концов вы получаете ненужный Zooпарк приложений, не относящихся к разработке на nodejs. В конце концов, вам все равно надо будет еще cygwin ставить, чтобы питон запускать. Т.е. все эти крендебобили с Microsoft продуктами вообще не нужны.
        +6
        cool story, bro.
          0
          Зачем тут нужен IIS хорошо описал Скотт Хансельман в своем блоге
          www.hanselman.com/blog/InstallingAndRunningNodejsApplicationsWithinIISOnWindowsAreYouMad.aspx
          Раздел «Why would I want node.js to run on Windows and IIS?»
            +3
            Спасибо, я прошелся по ссылке и сделал вывод, что это имеет смысл для production окружения, что очевидно. В статье, однако речь идет об окружении разработчика и в этом случае заниматься поднятием IIS сервера, имхо, является неким overhead'ом снижающим скорость разработки, когда голого nodejs достатчно ввиду поддержки IDE, например в Idea.

            Зачем он нужен на дев машине?
          +4
          Хмм… А я, дурак node.exe server.js запускал. И nginx.
          В качестве Mysql-модуля используется библиотека от хабрапользователя Sannis, которую надо собирать или медленная (но нативная) github.com/felixge/node-mysql?
            +1
            Зачем же так? Мы поддержку Node.js только месяц как сделали, вы не могли об этом знать.
            Использовали нативный node-mysql. Мы все же не базу данных меряли, а просто хотели «утяжелить» запрос, чтобы показать как меняется график.
              0
              Ну я node.exe (без установки в систему цугвина) ещё год назад запускал. Потому и так, и как то не видел с этим проблем, сейчас вот прикидываю плюсы Web Platform Installer.
                0
                Плюс в том что это продакшн решение на IIS. Если вы будете разворачивать его потом на Windows сервере, то это самый прямой путь. Ну и плюс что все в одном месте ставится за пару кликов — не нужно бегать по ссылкам и собирать пакеты.
                  0
                  WebMatrix это продакшн решение?
                    0
                    В статье есть глава «Развертывание на сервере».

                    Неужели вы думаете мы на WebMatrix-е обогнали Linux сервер во всех тестах?
            0
            Про установку модулей в обход npm не знал. Надо попробовать поставить пакеты проверки скриптов и запуска юнит-тестов и прикрутить их к maven'у. Не совсем традиционное использование Нода, но для нас было бы очень кстати.
              0
              Отличная статья, спасибо!
              Теперь становится понятным зачем нужен продукт WebMatrix профессионалам.
              • UFO just landed and posted this here
                  +2
                  Нет. Мы не работаем на Microsoft и даже никак с ними не связаны. В каком-то смысле мы даже конкурируем с ними, причем делаем это на их платформе, так что надежд мало…

                  Мы выпускаем продукты чтобы удовлетворить существующую потребность. Так уж вышло что продукты эти серверные. И выпускаем мы их на той платформе где есть спрос и где у нас есть опыт.

                  Microsoft часто выпускает затем аналогичные продукты. Взять например iisnode, который вышел после Helicon Zoo и значительно уступает ему, но о нем уже масса статей. Ну некому у нас статьи писать.

                  Или когда Microsoft встроила URL Rewrite Module в 2008 сервер, полностью вытеснив наш ISAPI_Rewrite с рынка.

                  О нашем Ape я могу долго рассказывать. Этот продукт в разы превосходит URL Rewrite module и ARR вместе взятые как по производительности так и по возможностям, но так и не стал популярным, потому что затем появились вышеназванные встроенные аналоги. А папуляризовать наше решение некому.

                  Так что не торопитесь ставить минус «поборникам корпорации зла» — правда как всегда где-то посредине.
                  • UFO just landed and posted this here
                      0
                      iisnode популярен и будет популярен потому, что разработчику, который хочет использовать node на Windows, нужно только то, что ему нужно. Ему не нужен ещё один пакетный менеджер. Ваше решение, судя по внешнему виду, подходит болше какому-нибудь хостинг-провайдеру, чем рядовому разработчику. А вы его хотите протолкнуть разработчикам.
                        0
                        Согласен, кто предпочитает все ставить руками, тому «еще один» пакетный менеджер не нужен.
                        Как метко подметили выше, iisnode кстати тоже не нужен — node.exe работает и без хитроумных менеджеров процессов, балансировщиков и веб серверов.
                    0
                    Крайне полезной фичей для хостинга NodeJS является IISNode — дополнение для IIS, позволяющее не «светить» открытый порт в мир (то есть порты IIS и NodeJS будут для клиентского браузера идентичными, работает через именованые пайпы, по заверениям автора — не блокирует собственную очередь IIS-соединений).

                    Умеет запускать по потоку на ядро процессора (конфигурируемо), перезагружать NodeJS при внезапной «смерти» процесса.

                    Автор сего чуда — Томаш Янчук, работает в «Майкрософте», оперативно отвечает на тикеты с описаниями проблем.

                    Его наработку используем на «боевом» сервере — проблем пока не выявили.
                      0
                      А драйвера для MS SQL Server не присоветуете? Гугль молчит как рыба об лед, толковых решений не предлагает. Их что, вообще не существует!?
                        0
                        Нет. Насколько я могу судить, пока что это мало кого интересует.
                          0
                          К сожалению, не присоветую — у нас MуSQL.
                          0
                          Может тогда попробуете наше решение? Мы не работаем в Майкрософте, но Helicon Zoo намного лучше iisnode. И по скорости и по надежности и по возможностям, да и устанавливать проще.
                            +1
                            Ярослав, а можно где-то почитать, что умеет Helicon Zoo в применении к NodeJS?
                            Вы говорите «намного лучше и быстрее» — интересует, чем именно и какие то сравнительные тесты.

                            Меня в IISNode радует возможность «прятать» внешний порт, в примере Вашей статьи порт виден наружу. Посмотрел официальный сайт — там о такой возможности ничего не увидел :(.

                            Может, плохо смотрел?
                              +1
                              Если вы про скриншоты, то там порт IIS Express, к Node.js он отношения не имеет.

                              Разумеется все так и работает. Helicon Zoo — это такой HTTP/FastCGI прокси со встроенным балансировщиком и менеджером процессов. Преимущество в том что работает он автоматически — самостоятельно создает процессы node.exe (и не только) по мере необходимости (нагрузка и т.п.) и самостоятельно их ресайклит, и делает все это быстро.

                              Еще кстати через IIS с легкостью проксируется Comet, в продакшене. Больше не нужно запускать отдельный процесс для обработки long polling запросов.
                                0
                                Посмотрю надосуге.

                                А вообще, странно, что Майкрософт, вместо того, что бы придти к Вам с предложением, предпочитает переписывать заново.

                                «Еще кстати через IIS с легкостью проксируется Comet, в продакшене. Больше не нужно запускать отдельный процесс для обработки long polling запросов.» — что Вы имеете ввиду? У меня как раз Комет-подобное решение бегает под IISNode, никаких отдельных процессов, кроме ноды, я не использую.
                                  0
                                  Это было про Апач — у него были проблемы с проксированием Comet в продакшене. Т.к. на каждый запрос выделяется по процессу он не выдерживал нагрузки когда количество подключений возрастало. У Nginx помоему тоже была проблема с количеством подключений к бекэнду если проксировать через него comet.
                                    +1
                                    А, безусловно.

                                    Но подобную проблему под Apache и NGinx успешно решал автор VooDoo Chat при помощи своих mod_voc2 и mod_nginx еще в 2005-2006 годах.

                                    Напрямую проксировать, естественно — это убийство сервера, так как веб-сервер держит открытый коннект на все время long pooling сессии.

                                    Описанные выше модули как раз и учили веб-сервер «забывать» о таком соединении, не закрывая сокет.
                          +1
                          Недавно хотел познакомится с Node.js и тут как раз подробная статья. Спасибо!
                            +1
                            Исходники микрочата из статьи: https://gist.github.com/1348247
                              +1
                              Вопрос: а какой смысл в ноде под вин на продакшне, если libev откатывается на использование select() (вернее, WSASelect()) и в связи с этим теряет всю привлекательность в производительности? Для разработки понятно, но тогда, на мой взгляд, окружение node.exe + nginx поднять проще.
                                0
                                Все же прочитайте тесты производительности в статье. Как бы удалось получить такой результат, если бы все было на самом деле так плохо?
                                Node.js официально использует libuv начиная с версии 0.6.0 и там все гораздо лучше.
                                  +1
                                  libuv, насколько я понимаю, всего лишь обертка над libev и IOCP для унификации кроссплатформенного API. Т.е. никаких чудес производительности от нее ждать не приходится. Да и странно было бы это — насколько я знаю ничего подобного kqueue/epoll/etc. под вин нет и пока не планируется.

                                  Ваши замеры производительности не совсем помогают оценить ситуацию, поскольку не дают информации о масштабируемости решения по возрастанию кол-ва запросов/времени.

                                  Я не утверждаю, что селект сам по себе тормоз, он просто начинает проседать при определенном количестве опрашиваемых сокетов в силу архитектуры (необходимость использования битовой маски под каждый сокет).
                                    0
                                    Правильно, libuv — это обертка, которая на Unix использует libev, а на Windows использует IOCP.
                                    IOCP — это аналог libev на Windows. Несмотря на то что технологически они совершенно разные, функционально это прямой аналог. Так что никаких select и прочих ужасов.

                                    Вот только недавно статья об этом была: habrahabr.ru/blogs/nodejs/131944/
                                      +1
                                      Может, все-таки аналог poll/epoll? Потому что libev, в свою очередь, лишь обертка на этими механизмами.

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

                                      К сожалению, не могу найти достаточно полной статьи по IOCP, если бы вы смогли поделиться ссылкой на описание внутренних механизмов его работы и парой примеров — был бы признателен.
                                        0
                                        Не скажу чего аналог, потому что они одинаково не похожи ни на libev ни на epoll, но задача у них — поддержка асинхронных операций ОС, в частности ввода-вывода.
                                        Документации и правда очень мало. Вот что мне дал разработчик:

                                        Вот про порты msdn.microsoft.com/en-us/library/windows/desktop/aa365198(v=vs.85).aspx
                                        Так мы его создаем msdn.microsoft.com/en-us/library/windows/desktop/aa363862(v=vs.85).aspx
                                        Так читаем msdn.microsoft.com/en-us/library/windows/desktop/aa364986(v=vs.85).aspx
                                        CreateIoCompletionPort так же используется для ассоциировать сокет/файл с портом. (названа функция крайне не удачно)
                                          0
                                          Вот это вот наводит на некоторые размышления и сомнения:

                                          NumberOfConcurrentThreads [in]

                                          The maximum number of threads that the operating system can allow to concurrently process I/O completion packets for the I/O completion port. This parameter is ignored if the ExistingCompletionPort parameter is not NULL.

                                          If this parameter is zero, the system allows as many concurrently running threads as there are processors in the system.

                                          Знать бы как оно работает внутри…

                                          Наглый вопрос: не могли бы вы сделать графики зависимости пропускной способности от кол-ва открытых соединений? Интересно, где находится «яма», после которой начинает проседать производительность (а она обязательно должна быть :)).
                                            0
                                            «NumberOfConcurrentThreads [in]» — это число потоков, обслуживающих СР. Если они неблокирующие, то их нужно столько сколько ядер. Увеличение их числа не приведет к приросту производительности, а значительное увеличение даже снизит ее (накладные расходы).

                                            По тесту попробую что ни будь придумать, но не обещаю. Такое количество соединений нужно еще чем-то генерировать, а у нас тут не ВЦ. И велика вероятность упереться в яму на клиенте/транспорте, т.е. будет неизвестно что же на самом деле померяли.
                                              0
                                              Есть же средства стресс-тестирования, pylot, например. При правильной настройке он и графики сам нарисует. Думаю, многие, включая меня, были бы вам весьма благодарны.

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

                                              NumberOfConcurrentThreads [in]


                                              На самом деле не должно. Ожидать более, чем «there are processors in the system» не имеет смысла. Следует понимать, что на IOCP можно заблокировать и больше, чем NumberOfConcurrentThreads потоков, но они не

                                              Знать бы как оно работает внутри…


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

                                              DISPATCHER_OBJECT (в общем все, что можно ждать при помощи NtWaitForXxxObject, в том числе и файлы) можно ассоциировать с очередью (KQUEUE). Когда объект переводится в signaled state (файлы «сигнализируются» когда завершается операция ввода/вывода для этого файла), в эту очередь, если она есть, добавляется wait-блок. GetQueuedCompletionStatus (вернее его native помощник NtRemoveIoCompletion) блокируется пока в этой очереди не появится чего нибудь.

                                              Если еще короче, в объекте-IOCP есть очередь, а в файлах, ассоциированных с этим IOCP есть указатель на эту очередь. Вот и вся история.

                                              Отвечая на начальный вопрос, WSAXxxSelect (и синхронный select) и IOCP — совершенно разные подходы, причем IOCP более изящный и зачастую более производительный. select отмечает момент времени, когда можно произвести «блокирующее» чтение/запись в файл без, собственно, блокирования (например, когда есть данные в буфере для recv) и предназначен для работы с этими синхронными версиями (send/recv/etc).

                                              В то же время IOCP позволяет определить момент завершения асинхронной операции, требует использования асинхронных вызовов (WSASend/WSARecv/etc), позволяет избавиться от промежуточной буферизации: TCP/IP стек может копировать данные прямо в ожидающий пользовательский буфер, а в случае TOE пользовательский буфер может быть заполнен прямо сетевой картой по DMA. В случае send (и других операция тоже, включая recv, просто для send выгода не так очевидна), настоящие асинхронные операции позволяют опять же избавиться от промежуточного буфера (TCP/IP может «владеть» пользовательским буфером без необходимости срочно скопировать его куда нибудь и отпустить поток), а также это позволяет избавиться от задержек (latency) между готовностью к выполнению следующей операции и собственно выполнением этой операции: приложение может запостить несколько операций чтения/записи подряд — подход, используемый например в высокопроизводительной графике, для снижения задержек (double/triple-buffering).
                                                0
                                                О, спасибо за развернутый ответ!
                                                Осталось переварить и понять, почему технология времен NT 3.5 так непопулярна была.
                                                  0
                                                  Перечитал. Несколько сумбурно (не быть мне tech writer-ом), а в одном месте вообще мысль оборвалась (все не могу выработать привычку перечитывать перед нажатием на «submit»), но в целом мысль должна быть ясна.

                                                  На всякий случай попробую прояснить суть с другой стороны: важно понимать отличие асинхронной операции от неблокирующей. Неблокирующие операции просто обязаны вернуться сразу же: если они не могут выполнить что-нибудь осмысленное, то они могут вернуться с ошибкой (например, EWOULDBLOCK). Асинхронная же операция это такая, которая может выполняться «в фоне», то есть операция выполняется всегда: если можно выполнить сразу — выполняем сразу, если нельзя — *инициируем* операцию и возвращаемся сразу. Все асинхронные операции неблокирующие, но не все неблокирующие операции асинхронные.

                                                  Из этой разницы и следует разница между IOCP и select. IOCP работает с асинхронными операциями и позволяет отреагировать на завершение операции, инициированной где-то в другом месте. select же (в том числе и «асинхронная» версия САМОГО select — WSAXxxSelect) работает с (не)блокирующими операциями. То есть можно создать «неблокирующий» сокет, recv (или read) из которого будет всегда возвращать ошибку, если в буфере пусто, но запостить собственный буфер для ожидания в него данных нельзя.

                                                  Насчет непопулярности спорно. Технология всегда была весьма популярна в high-load Windows приложениях. За пределами high-load использование асинхронности просто не имело смысла (ее труднее понять а если выгода неочевидна, то использование синхронных вызовов попросту легче). А за пределами Windows все по разному: на BSD/Solaris были свои аналоги, на Linux же поддержки асинхронных операций вообще не было до относительно недавнего времени (а как по мне, их и сейчас толком нет).
                                  –1
                                  А что такое ubunthu?
                                    –1
                                    После изучения графиков тоже стало интересно :)
                                      0
                                      Это опечатка.
                                      Использовали Ubuntu Server 11.04 x64.
                                        0
                                        Я понимаю, что опечатка.

                                        Сейчас релоаднул графики — все еще «Ubunthu».
                                      0
                                      Усли бы не верхний бар в WebMatrix получился неполохой такой редактор. Его можно как то спрятать?
                                      intellisense работает для node и других языков?
                                        0
                                        Хм… Вы что до этого никогда Ribbon-интерфейс не видели? Он сворачивается по двойному клику на табе.
                                        –4
                                        > Особенно приятно, что Node.js одинаково хорошо как на Unix, так и на Windows, и использует правильные для каждой из этих операционных систем технологические решения, что отчетливо видно по результатам тестов.

                                        Ubuntu не Unix. Давайте тесты на FreeBSD, Gentoo, CentOS и Debian. Мне кажется, что у кого-то руки из жопы растут :)
                                          0
                                          линукс вообще не юникс. кроме того, ваше утверждение о том, что убунту чем-то хуже остальных дистров без аргументов не состоятельно
                                            –1
                                            неоптимальные дефолтные конфиги. Windows с NTFS при всем своем желании не может быть быстрее Linux с EXT4. Уж проверяли, знаем.
                                              0
                                              конфиги это конфиги, так можно дойти до того, что если в гноме обои фиговые — дистр плохой.
                                              щас мы и спросим у автора что за величина у него измеряна и как так получилось
                                                –1
                                                Я где-то говорил, что Ubuntu плохая? Я говорю о том, что тестировать нужно на всех дистрибутивах и брать среднее значение. А тут какой-то вброс.
                                          +1
                                          скажите, пожалуйста, вот у вас нарисованы какие-то диаграммы в каком-то редакторе по каким-то данным — назревают вопросы:
                                          1. что за величина на графике изображена? попугаи какого цвета? с какими конфигами были достигнуты такие результаты на апаче и винде?
                                          2. почему вы нарисовали это всё в каком-то табличном процессоре, в то время как у ab есть встроенная возможность экспорта данных в формат понятный GNUPlot для построения честных кривых?

                                          пока что мне всё это напоминает картинку, высосанную из пальца. ниже грубый пример нормальных бенчмарков

                                            0
                                            *на апаче на линуксе и винде
                                              0
                                              Хорошо, дайте нам несколько дней — постараемся сделать более подробные графики. Заодно опечатку исправлю раз она так глаза мозолит.
                                              Попугаи на графиках — запросы в секунду.
                                                0
                                                ещё конфиги там и там очень интересуют, подозреваю, что они совсем не одинаковые
                                                  0
                                                  Только что обновил статью с графиками и конфиги приложил. Смотрите.
                                              –1
                                              Ждем запуска Node.js на Denwer…
                                              Это не шутка!..
                                                0
                                                Добавьте у статьи тег «javascript».
                                                  0
                                                  Запускаю сайт, получаю ошибку:
                                                  500. Oops, something wrong in FastCgi module

                                                  Can't connect to a child process. Please, check configuration.
                                                  Операция успешно завершена.
                                                  dwError=0
                                                  TcpTransport.cpp: 108

                                                  Кто-нибудь сталкивался с такой?
                                                    0
                                                    Да. Эта ошибка означает что Zoo запустил воркер (в данном случае очевидно node.exe), но так и не дождался от него ответа. Причин может быть миллион — от синтаксической ошибки в скрипте запуска сервера, до недостаточных прав на папку с модулями или скриптами. Напишите нам в поддержку, постараемся выяснить в чем дело — support.helicontech.com/
                                                      0
                                                      Да, судя по «Операция успешно завершена.» это русская винда и вы видимо запускаете IIS Express? Node.js не понимает русские символы в пути к скриптам и падает, а т.к. сайты IIS Expres по умолчанию находятся в «Мои документы», то тут все и падает. Мы не можем это исправить со своей стороны, это ошибка Node.js.
                                                      0
                                                      Спасибо за ответ, но после переустановки Win, все заработало.
                                                        0
                                                        К сожалению проблема осталась. Однако если запускать код не из среды, то вроде работает. Вот пример:
                                                        var http = require('http');
                                                        http.createServer(function (req, res) {
                                                        res.writeHead(200, {'Content-Type': 'text/plain'});
                                                        res.end('Hello World\n');
                                                        }).listen(8000);
                                                        console.log('Server running at 127.0.0.1');


                                                        Если через cmd запускаю так: node.exe server.js, то запускается нормально. Если тот же скрипт запускаем из среды, то запускается браузер однако ничего не происходит. Браузер показывает индиатор загрузки, но этот процесс не прекращается.
                                                          0
                                                          .listen(8000);
                                                          заменить на
                                                          .listen(process.env.PORT);

                                                          в статье об этом есть.
                                                          Хотя, опять же повторюсь, с проблемами пишите к нам на суппорт. Хабр — не место для расследований проблем.
                                                          0
                                                          С появлением WebMatrix 2 Beta приложение Web Platform Installer обновилось до 4-й версии и ваш фид не подтягивает. А 3-ю версию уже не поставить
                                                            0
                                                            Да, для WebPI 4.0 нужно использовать фид по адресу www.helicontech.com/zoo/feed/4/
                                                            Microsoft вкурсе проблемы, они обещали в RC версии WebMatrix 2 исправить. Когда исправят — будет один фид для всех версий.
                                                              0
                                                              что-то или я тупой, или лыжи не едут.

                                                              Поставил на ВМ2 ноде темплейт, получил хеллоу, но когда пытаюсь вставить код из примера сервер отдает закешированную версию (хеллоу). Но в ВМ2 кнопки рестарт нету
                                                                0
                                                                В предыдущей версии могли быть проблемы со слежением за изменениями *.js файлов. Пожалуйста обновите версию Zoo Module: Zoo -> Modules -> Helicon Zoo Module for IIS Express — просто нажать установить еще раз. WebMatrix нужно будет перезапустить.
                                                                Если и это не поможет, то в web.config в секцию добавьте строку:
                                                                />
                                                                Просто под WebMatrix 2 Beta у нас пока нет автотестирования, но это временно.
                                                                  0
                                                                  Теги скушались. Нужно так:
                                                                  <environmentVariables>
                                                                  <add name="WATCH_FILE_CHANGES_MASK" value="*.js" />
                                                                    0
                                                                    похоже проблема была в «Мои документы».

                                                                    Вы так быстро отвечаете… можно еще вопрос? Как сделать coffeescript? Модуль-то для линукса тянется из ryppi
                                                                      0
                                                                      К сожалению с coffescript сильно не помогу т.к. сам не очень разбираюсь. Модуль который устанавливается работает на Windows, но не работает команда coffee из командной строки (хотя и ее как-то можно уговорить скорее всего). Само применение которое рекомендуют в документации включает в себя запуск слежения за изменениями файлов, очевидно отдельным процессом node.exe. Мне же кажется что вызов компиляции .coffee файлов прямо из кода будет более надежным решением. В любом случае тут нужно делать обертку (возможно она уже есть, но я о ней не знаю). Спросите на более специальном форуме, возможно там подскажут.

                                                          Only users with full accounts can post comments. Log in, please.