Подтвердить что ты не робот

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

- Я создал простое приложение, которое извлекает данные (50 элементов) из Redis DB и выдает его на localhost. Я сделал ApacheBench (c = 100, n = 50000), и я получаю полупристойные 150 запросов/сек на двухъядерном T2080 @1,73 ГГц (мой ноутбук на 6 лет), но использование proc очень неутешительно, поскольку показано: 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 );

Я также хочу подчеркнуть, что приложение является интенсивным вводом-выводом (не интенсивно с CPU), что сделало бы что-то вроде threads-a-gogo лучший выбор, чем кластеры).

Было бы полезно помочь в этом.

4b9b3361

Ответ 1

На самом деле, ваша рабочая нагрузка не связана с привязкой ввода/вывода: она связана с CPU из-за стоимости создания динамических страниц на основе jade. Я не могу угадать сложность вашего шаблона нефрита, но даже с помощью простых шаблонов генерация 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 req/s с процессором node.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 req/s. Таким образом, узкое место явно связано с форматированием 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% потреблении процессора (для сравнения с начальными 475 req/s).