簡體   English   中英

Node.js 比 Apache 慢

[英]Node.js slower than Apache

我正在比較 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 Bench 時針對Apache使用以下參數

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)

針對節點實例運行 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 開始丟棄其中的一些,而節點工作正常,沒有連接丟失。

動態請求

node.js 非常擅長處理大量小的動態請求(可以是掛起/長輪詢)。 但它不擅長處理大緩沖區。 Ryan Dahl(作者 node.js)解釋了他的演示文稿之一。 我建議您學習這些幻燈片。 我也在某處網上看過這個。

垃圾收集器

正如您從幻燈片(45 中的 13)中看到的那樣,它不適合大緩沖區。

幻燈片 15 從 45:

V8 有一個分代垃圾收集器。 隨機移動物體。 節點無法獲取指向原始字符串數據的指針以寫入套接字。

使用緩沖區

幻燈片 16 從 45

使用 Node 的新 Buffer object,結果發生了變化。

仍然不如 nginx 好,但要好得多。 這些幻燈片也很舊,所以可能 Ryan 甚至改進了這一點。

內容分發網絡

我仍然認為您不應該使用 node.js 來托管 static 文件。 您可能最好將它們托管在針對托管 static 文件進行了優化的 CDN 上。 一些流行的 CDN (有些甚至是免費的)通過 WIKI。

NGinx(+Memcached)

如果您不想使用 CDN 來托管 static 文件,我建議您將Nginx 與 memcached一起使用,這非常快。

在這種情況下,Apache 可能正在發送文件,這導致kernel將 memory 數據塊(由 fs 驅動程序緩存)直接發送到套接字。 在節點的情況下,在 v8、libeio 和 kernel 之間復制用戶空間中的數據會產生一些開銷(請參閱這篇關於在節點中使用 sendfile 的精彩文章)

在很多可能的情況下,節點的性能將優於 Apache,例如“將 stream 的數據以恆定的低速發送到盡可能多的 tcp 連接”

如果您增加並發性並在 node.js 中使用緩存,您的基准測試結果可能會更改為有利於 node.js

“Node Cookbook”一書中的示例代碼:

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

實際上,您在這里所做的只是讓系統在不同進程的地址空間中的 memory 中的緩沖區之間復制數據 - 磁盤緩存意味着您並沒有真正接觸磁盤,而是使用本地 sockets。

因此,每個請求必須完成的副本越少,速度就越快。

編輯:我建議添加緩存,但實際上我現在看到您已經這樣做了 - 您讀取文件一次,然后啟動服務器並每次發送回相同的緩沖區。

您是否嘗試過預先將 header 部分附加到文件數據中,因此您只需為每個請求執行一次寫入操作?

$ 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

在以下基准中,

Apache:

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

PHP APC 緩存/加速器已安裝。

在我的筆記本電腦上進行測試,Sager NP9280 配備 Core I7 920、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 整潔

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM