Node.js比Apache慢

时间:2011-07-09 10:54:06

标签: performance apache node.js apache2

我正在比较Node.js(0.5.1-pre)与Apache(2.2.17)的性能,这是一个非常简单的场景 - 提供文本文件。

这是我用于节点服务器的代码:

var http = require('http')
  , fs = require('fs')

fs.readFile('/var/www/README.txt',
    function(err, data) {
        http.createServer(function(req, res) {
            res.writeHead(200, {'Content-Type': 'text/plain'})
            res.end(data)
        }).listen(8080, '127.0.0.1')
    }
)

对于Apache,我只使用Ubuntu 11.04的任何默认配置

使用以下参数对 Apache

运行Apache Bench时
ab -n10000 -c100 http://127.0.0.1/README.txt

我得到以下运行时:

Time taken for tests:   1.083 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      27630000 bytes
HTML transferred:       24830000 bytes
Requests per second:    9229.38 [#/sec] (mean)
Time per request:       10.835 [ms] (mean)
Time per request:       0.108 [ms] (mean, across all concurrent requests)
Transfer rate:          24903.11 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.8      0       9
Processing:     5   10   2.0     10      23
Waiting:        4   10   1.9     10      21
Total:          6   11   2.1     10      23

Percentage of the requests served within a certain time (ms)
  50%     10
  66%     11
  75%     11
  80%     11
  90%     14
  95%     15
  98%     18
  99%     19
 100%     23 (longest request)

在针对 node 实例运行Apache bench时,这些是运行时:

Time taken for tests:   1.712 seconds
Complete requests:      10000
Failed requests:        0
Write errors:           0
Total transferred:      25470000 bytes
HTML transferred:       24830000 bytes
Requests per second:    5840.83 [#/sec] (mean)
Time per request:       17.121 [ms] (mean)
Time per request:       0.171 [ms] (mean, across all concurrent requests)
Transfer rate:          14527.94 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.9      0       8
Processing:     0   17   8.8     16      53
Waiting:        0   17   8.6     16      48
Total:          1   17   8.7     17      53

Percentage of the requests served within a certain time (ms)
  50%     17
  66%     21
  75%     23
  80%     25
  90%     28
  95%     31
  98%     35
  99%     38
 100%     53 (longest request)

这显然比Apache慢。如果您考虑到Apache正在执行许多其他操作(例如日志记录等)这一点,这一点尤其令人惊讶。

我做错了吗?或者在这种情况下Node.js真的慢了吗?

编辑1 :我注意到节点的并发性更好 - 当同时将请求数增加到1000时,Apache开始丢弃其中一些,而节点工作正常,没有连接丢失。

6 个答案:

答案 0 :(得分:25)

动态请求

node.js非常善于处理很多小动态请求(可以挂起/长轮询)。但它不擅长处理大缓冲区。 Ryan Dahl(作者node.js)解释了这一his presentations。我建议你研究这些幻灯片。我也在网上看过这个。

垃圾收集器

正如你从幻灯片中看到的那样(13从45开始),大缓冲区很糟糕。

从45开始滑动15:

  

V8有一代人垃圾   集电极。移动物体   随机。节点无法获取指针   要写入套接字的原始字符串数据。

使用缓冲区

从45开始滑动

  

使用Node的新Buffer对象   结果发生了变化。

仍然没有那么好,例如nginx,但好多了。这些幻灯片也很老了,所以Ryan甚至可以改进它。

CDN

我仍然认为您不应该使用node.js来托管静态文件。您最好将它们托管在CDN上,该CDN针对托管静态文件进行了优化。通过WIKI Some popular CDN(有些甚至免费)。

NGINX(+ Memcached的)

如果您不想使用CDN来托管您的静态文件,我建议您使用Nginx with memcached而不是非常快。

答案 1 :(得分:20)

在这种情况下,Apache可能会执行sendfile,这会导致内核将内存数据块(由fs驱动程序缓存)直接发送到套接字。在节点的情况下,在v8,libeio和kernel之间的用户空间中复制数据会有一些开销(参见this关于在节点中使用sendfile的好文章)

有很多可能的情况,节点将胜过Apache,例如“以尽可能多的tcp连接以尽可能多的速度发送数据流”

答案 2 :(得分:3)

如果增加并发性并在node.js中使用缓存,则基准测试的结果可能会更改为node.js

“节点食谱”一书中的示例代码:

var http = require('http');
var path = require('path');
var fs = require('fs');
var mimeTypes = {
    '.js' : 'text/javascript',
    '.html': 'text/html',
    '.css' : 'text/css'
} ;
var cache = {};
function cacheAndDeliver(f, cb) {
    if (!cache[f]) {
        fs.readFile(f, function(err, data) {
            if (!err) {
                cache[f] = {content: data} ;
            }
            cb(err, data);
        });
        return;
    }
    console.log('loading ' + f + ' from cache');
    cb(null, cache[f].content);
}
http.createServer(function (request, response) {
    var lookup = path.basename(decodeURI(request.url)) || 'index.html';
    var f = 'content/'+lookup;
    fs.exists(f, function (exists) {
        if (exists) {
            fs.readFile(f, function(err,data) {
                if (err) { response.writeHead(500);
                    response.end('Server Error!'); return; }
                    var headers = {'Content-type': mimeTypes[path.extname(lookup)]};
                    response.writeHead(200, headers);
                    response.end(data);
                });
            return;
        }
response.writeHead(404); //no such file found!
response.end('Page Not Found!');
});

答案 3 :(得分:1)

你真正在这里做的就是让系统在内存中的缓冲区之间,在不同进程的地址空间中复制数据 - 磁盘缓存意味着你并没有真正触及磁盘,而你正在使用本地套接字。 / p>

因此,每个请求必须完成的副本越少,就越快。

编辑:我建议添加缓存,但实际上我现在看到你已经这样做了 - 你读了一次文件,然后启动服务器并每次发送回相同的缓冲区。 / p>

您是否曾尝试将标题部分附加到文件数据中,因此您只需为每个请求执行一次写操作?

答案 4 :(得分:0)

$ cat /var/www/test.php
<?php
for ($i=0; $i<10; $i++) {
        echo "hello, world\n";
}


$ ab -r -n 100000 -k -c 50 http://localhost/test.php
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests


Server Software:        Apache/2.2.17
Server Hostname:        localhost
Server Port:            80

Document Path:          /test.php
Document Length:        130 bytes

Concurrency Level:      50
Time taken for tests:   3.656 seconds
Complete requests:      100000
Failed requests:        0
Write errors:           0
Keep-Alive requests:    100000
Total transferred:      37100000 bytes
HTML transferred:       13000000 bytes
Requests per second:    27350.70 [#/sec] (mean)
Time per request:       1.828 [ms] (mean)
Time per request:       0.037 [ms] (mean, across all concurrent requests)
Transfer rate:          9909.29 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       3
Processing:     0    2   2.7      0      29
Waiting:        0    2   2.7      0      29
Total:          0    2   2.7      0      29

Percentage of the requests served within a certain time (ms)
  50%      0
  66%      2
  75%      3
  80%      3
  90%      5
  95%      7
  98%     10
  99%     12
 100%     29 (longest request)

$ cat node-test.js 
var http = require('http');
http.createServer(function (req, res) {
          res.writeHead(200, {'Content-Type': 'text/plain'});
            res.end('Hello World\n');
}).listen(1337, "127.0.0.1");
console.log('Server running at http://127.0.0.1:1337/');

$ ab -r -n 100000 -k -c 50 http://localhost:1337/
This is ApacheBench, Version 2.3 <$Revision: 655654 $>
Copyright 1996 Adam Twiss, Zeus Technology Ltd, http://www.zeustech.net/
Licensed to The Apache Software Foundation, http://www.apache.org/

Benchmarking localhost (be patient)
Completed 10000 requests
Completed 20000 requests
Completed 30000 requests
Completed 40000 requests
Completed 50000 requests
Completed 60000 requests
Completed 70000 requests
Completed 80000 requests
Completed 90000 requests
Completed 100000 requests
Finished 100000 requests


Server Software:        
Server Hostname:        localhost
Server Port:            1337

Document Path:          /
Document Length:        12 bytes

Concurrency Level:      50
Time taken for tests:   14.708 seconds
Complete requests:      100000
Failed requests:        0
Write errors:           0
Keep-Alive requests:    0
Total transferred:      7600000 bytes
HTML transferred:       1200000 bytes
Requests per second:    6799.08 [#/sec] (mean)
Time per request:       7.354 [ms] (mean)
Time per request:       0.147 [ms] (mean, across all concurrent requests)
Transfer rate:          504.62 [Kbytes/sec] received

Connection Times (ms)
              min  mean[+/-sd] median   max
Connect:        0    0   0.1      0       3
Processing:     0    7   3.8      7      28
Waiting:        0    7   3.8      7      28
Total:          1    7   3.8      7      28

Percentage of the requests served within a certain time (ms)
  50%      7
  66%      9
  75%     10
  80%     11
  90%     12
  95%     14
  98%     16
  99%     17
 100%     28 (longest request)

$ node --version
v0.4.8

答案 5 :(得分:0)

在以下基准中,

的Apache:

$ apache2 -version
Server version: Apache/2.2.17 (Ubuntu)
Server built:   Feb 22 2011 18:35:08

安装了PHP APC缓存/加速器。

在我的笔记本电脑上测试,带有Core I7 920的Sager NP9280,12G内存。

$ uname -a
Linux presto 2.6.38-8-generic #42-Ubuntu SMP Mon Apr 11 03:31:24 UTC 2011 x86_64 x86_64 x86_64 GNU/Linux

KUbuntu natty