Как использовать кластеры Node.js с моим простым приложением Express?

& # X2014; Я создал простое приложение, которое извлекает данные (50 элементов) из базы данных Redis и выбрасывает их на локальный хост. Я сделал ApacheBench (c = 100, n = 50000) и получаю полудойные 150 запросов / сек на двухъядерном T2080 с частотой 1,73 ГГц (мой 6-летний ноутбук), но использование процедуры очень разочаровывает, так как показано: enter image description here

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

var 
    express = require( 'express' ),
    app     = express.createServer(),
    redis   = require( 'redis' ).createClient();

app.configure( function() {
    app.set( 'view options', { layout: false } );
    app.set( 'view engine', 'jade' );
    app.set( 'views', __dirname + '/views' );
    app.use( express.bodyParser() );
} );

function log( what ) { console.log( what ); }

app.get( '/', function( req, res ) {
    redis.lrange( 'items', 0, 50, function( err, items ) {
            if( err ) { log( err ); } else {
                res.render( 'index', { items: items } );
            }
    });
});

app.listen( 8080 );

Я также хочу подчеркнуть, что приложение интенсивно вводит / выводит (не загружает процессор, что могло бы сделать что-то вроденитей-а-Gogo лучший выбор, чем кластеры).

Хотелось бы помочь в выяснении этого.

Ответы на вопрос(1)

Решение Вопроса

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

Для своих тестов я использовал этот шаблон:

html(lang="en")
  head
    title Example
  body
    h1 Jade - node template engine
    #container
      ul#users
        each user in items
          li User:#{user}

Я добавил 100 фиктивных строк к ключу предметов в Redis.

На моем боксе я получаю 475 запросов в секунду с CPU узла.js на уровне 100% (что означает 50% -ое потребление ресурсов процессора на этом двухъядерном процессоре). Заменим:

res.render( 'index', { items: items } );

от:

res.send( '<html lang="en"><head><title>Example</title></head><body><h1>Jade - node template engine</h1><div id="container"><ul id="users"><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li><li>User:NOTHING</li></ul></div></body></html>' );

Теперь результат бенчмарка близок к 2700 рэк / с. Таким образом, узкое место явно связано с форматированием HTML-страницы.

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

var cluster = require('cluster')

if ( cluster.isMaster ) {
  for ( var i=0; i<2; ++i )
    cluster.fork();
} else {
  var
      express = require( 'express' ),
      app     = express.createServer(),
      redis   = require( 'redis' ).createClient();

  app.configure( function() {
      app.set( 'view options', { layout: false } );
      app.set( 'view engine', 'jade' );
      app.set( 'views', __dirname + '/views' );
      app.use( express.bodyParser() );
  });

  function log( what ) { console.log( what ); }

  app.get( '/', function( req, res ) {
      redis.lrange( 'items', 0, 50, function( err, items ) {
            if( err ) { log( err ); } else {
              res.render( 'index', { items: items } );
            }
      });
  });

  app.listen( 8080 );
}

Теперь результат теста близок к 750 req / s при 100% потреблении CPU (для сравнения с начальными 475 req / s).

 06 нояб. 2012 г., 16:03
Тебе стоит попробоватьNODE_ENV=production node app.js вместоnode app.js .
 19 мая 2012 г., 16:23
Согласно моим собственным тестам, самые быстрые - Swig, nTenjin, Thunder и DoT в этом порядке.
 vjk200519 мая 2012 г., 15:40
вау, спасибо !, это сработало очень хорошо & # x2014; imgur.com/Cpqy6 & # x2014; Я потратил большую часть вчера, поднимая его с 80 до 150, и теперь простой блок if делает всю эту работу похожей на арахис. Примечание о шаблонах было очень познавательным; Я знал, что будет некоторая стоимость, но не думал, что это будет «475–2700». большой. Могу ли я оптимизировать Express? Кстати, я также хотел бы поделиться статистикой процессора & # x2014; imgur.com/n7WPv & # x2014; Я поднялся до 15 рабочих, но оба ядра никогда не доходили до 100%. Я не включил постоянство Redis, поэтому он не должен касаться диска, но около 30К-запроса помечаю, что мой диск вращается как сумасшедший. Я что-то пропускаю?
 19 мая 2012 г., 15:51
Узкое место в исполнении не экспресс, а нефрит. Вы можете попробовать другой шаблонизатор (все еще работающий с Express). Вот список:github.com/joyent/node/wiki/modules#wiki-templating
 vjk200519 мая 2012 г., 15:56
& quot; Узкое место в производительности - не экспресс, а нефрит. & quot; & # X2014; упс, я имел в виду "нефрита" но сказал "экспресс". Что по твоему быстрее чем Джейд?

Ваш ответ на вопрос