如何在我的简单Express应用程序中使用Node.js集群?

时间:2023-01-13 12:12:24

— I built a simple app that pulls in data (50 items) from a Redis DB and throws it up at localhost. I did an ApacheBench (c = 100, n = 50000) and I'm getting a semi-decent 150 requests/sec on a dual-core T2080 @ 1.73GHz (my 6 y.o laptop), but the proc usage is very disappointing as shown: 如何在我的简单Express应用程序中使用Node.js集群?

- 我构建了一个简单的应用程序,从Redis数据库中提取数据(50项)并将其抛出到localhost。我做了一个ApacheBench(c = 100,n = 50000),我在双核T2080 @ 1.73GHz(我的6哟笔记本电脑)上得到了半正常的150请求/秒,但是proc使用非常令人失望图所示:

Only one core is used, which is as per design in Node, but I think I can nearly double my requests/sec to ~300, maybe even more, if I can use Node.js clusters. I fiddled around quite a bit but I haven't been able to figure out how to put the code given here for use with my app which is listed below:

只使用一个核心,这是根据Node中的设计,但我认为如果我可以使用Node.js集群,我几乎可以将我的请求/秒加倍到~300,甚至更多。我摆弄了很多但我无法弄清楚如何把这里给出的代码用于我的应用程序,如下所示:

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 );

I also want to emphasize that the app is I/O intensive (not CPU-intensive, which would've made something like threads-a-gogo a better choice than clusters).

我还想强调一下,这个应用程序是I / O密集型的(不是CPU密集型的,这会使得像thread-a-gogo这样的东西比集群更好)。

Would love some help in figuring this out.

想要解决这个问题会有所帮助。

1 个解决方案

#1


34  

Actually, your workload is not really I/O bound: it is CPU bound due to the cost of jade-based dynamic page generation. I cannot guess the complexity of your jade template, but even with simple templates, generating HTML pages is expensive.

实际上,您的工作负载并非真正的I / O限制:由于基于玉的动态页面生成的成本,它受CPU限制。我无法猜测你的jade模板的复杂性,但即使使用简单的模板,生成HTML页面也很昂贵。

For my tests I used this template:

对于我的测试,我使用了这个模板:

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

I added 100 dummy strings to the items key in Redis.

我在Redis的items键中添加了100个虚拟字符串。

On my box, I get 475 req/s with node.js CPU at 100% (which means 50% CPU consumption on this dual core box). Let's replace:

在我的盒子上,我得到475 req / s,node.js CPU为100%(这意味着这个双核盒子的CPU消耗为50%)。让我们替换:

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

by:

通过:

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>' );

Now, the result of the benchmark is close to 2700 req/s. So the bottleneck is clearly due to the formatting of the HTML page.

现在,基准测试的结果接近2700 req / s。因此,瓶颈显然是由HTML页面的格式化造成的。

Using the cluster package in this situation is a good idea, and it is straightforward. The code can be modified as follows:

在这种情况下使用群集包是个好主意,而且很简单。代码可以修改如下:

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 );
}

Now the result of the benchmark is close to 750 req/s with 100 % CPU consumption (to be compared with the initial 475 req/s).

现在,基准测试的结果接近750 req / s,CPU消耗为100%(与最初的475 req / s进行比较)。

#1


34  

Actually, your workload is not really I/O bound: it is CPU bound due to the cost of jade-based dynamic page generation. I cannot guess the complexity of your jade template, but even with simple templates, generating HTML pages is expensive.

实际上,您的工作负载并非真正的I / O限制:由于基于玉的动态页面生成的成本,它受CPU限制。我无法猜测你的jade模板的复杂性,但即使使用简单的模板,生成HTML页面也很昂贵。

For my tests I used this template:

对于我的测试,我使用了这个模板:

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

I added 100 dummy strings to the items key in Redis.

我在Redis的items键中添加了100个虚拟字符串。

On my box, I get 475 req/s with node.js CPU at 100% (which means 50% CPU consumption on this dual core box). Let's replace:

在我的盒子上,我得到475 req / s,node.js CPU为100%(这意味着这个双核盒子的CPU消耗为50%)。让我们替换:

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

by:

通过:

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>' );

Now, the result of the benchmark is close to 2700 req/s. So the bottleneck is clearly due to the formatting of the HTML page.

现在,基准测试的结果接近2700 req / s。因此,瓶颈显然是由HTML页面的格式化造成的。

Using the cluster package in this situation is a good idea, and it is straightforward. The code can be modified as follows:

在这种情况下使用群集包是个好主意,而且很简单。代码可以修改如下:

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 );
}

Now the result of the benchmark is close to 750 req/s with 100 % CPU consumption (to be compared with the initial 475 req/s).

现在,基准测试的结果接近750 req / s,CPU消耗为100%(与最初的475 req / s进行比较)。