【问题标题】:How do I use Node.js clusters with my simple Express app?如何在我的简单 Express 应用中使用 Node.js 集群?
【发布时间】:2012-05-26 16:30:34
【问题描述】:

——我构建了一个简单的应用程序,它从 Redis 数据库中提取数据(50 项)并将其发送到本地主机。我做了一个 ApacheBench(c = 100,n = 50000),我在双核 T2080 @ 1.73GHz(我的 6 年笔记本电脑)上获得了 150 个请求/秒,但 proc 的使用非常令人失望,因为显示:

只使用了一个核心,这与 Node 中的设计一致,但我认为如果我可以使用 Node.js 集群,我的请求数/秒几乎可以翻一番,达到约 300 个,甚至可能更多。我摆弄了很多,但我无法弄清楚如何将code given here 用于下面列出的我的应用程序:

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/O 密集型的(不是 CPU 密集型的,这会使 threads-a-gogo 之类的东西比集群更好)。

希望得到一些帮助来解决这个问题。

【问题讨论】:

    标签: javascript node.js redis express cluster-computing


    【解决方案1】:

    实际上,您的工作负载并不是真正的 I/O 限制:由于基于翡翠的动态页面生成的成本,它是 CPU 限制的。我猜不出你的翡翠模板有多复杂,但即使是简单的模板,生成 HTML 页面也很昂贵。

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

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

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

    在我的机器上,我得到 475 req/s,node.js CPU 为 100%(这意味着这个双核机器上的 CPU 消耗为 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,CPU 消耗为 100%(与最初的 475 req/s 相比)。

    【讨论】:

    • 哇,谢谢!,效果非常好——imgur.com/Cpqy6——我昨天大部分时间都把它从 80 推到 150,现在一个简单的 if 块让所有工作看起来像花生。关于模板的说明很有教育意义;我知道会有一些成本,但没想到会是“475 到 2700”大。我可以优化 Express 吗?顺便说一句,我还想分享 CPU 统计信息 — imgur.com/n7WPv — 我的工作人员多达 15 个,但两个内核从未达到 100%。我还没有启用 Redis 持久性,所以它不应该接触磁盘,但是在 30K 请求标记附近,我的磁盘疯狂旋转。我忽略了什么吗?
    • 性能瓶颈不是express而是jade。您可以尝试另一个模板引擎(仍在使用 express)。这是一个列表:github.com/joyent/node/wiki/modules#wiki-templating
    • "性能瓶颈不是express,而是jade。" ——哎呀,我的意思是“翡翠”,但说的是“快递”。在你看来,什么比 Jade 更快?
    • 根据我自己的基准,最快的依次是 Swig、nTenjin、thunder 和 doT。
    • 你应该试试NODE_ENV=production node app.js而不是node app.js
    猜你喜欢
    • 1970-01-01
    • 2020-02-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-12-14
    • 2012-01-20
    • 1970-01-01
    • 2018-04-04
    相关资源
    最近更新 更多