NodeJS 比 PHP 慢很多?

问题描述 投票:0回答:2

我目前在 Apache + PHP + MySQL 下运行一个小型 Web 服务器,并且想探索使用 NodeJS 的选项。服务器实际上做了两件事:

  1. 提供一些静态文件(HTML/CSS/图像资源等)
  2. 查询数据库(仅选择和插入,不更新或删除)

但是,我遇到了一些性能问题,我正在尝试找出问题所在。为了隔离问题,我创建了一个最小的 NodeJS 应用程序,它对 MySQL 运行查询并以 JSON 形式返回 50 行数据。下面是我的代码:

var express = require('express');
var compression = require('compression');
var mysql = require('mysql');

var db = mysql.createPool({
    host: <host>,
    user: <user>,
    password: <password>,
    database: <database>,
    debug: false
});

var app = express();
app.use(compression());

app.get('/data', function(req, res) {
    var sql = 'SELECT column_1, column_2 FROM table';
    db.query(sql, function (error, rows, fields) {
        if (error) throw error;
        res.json(rows);
    });
});

app.listen(3000, function () {
  console.log("Running on port 3000.");
});

使用 ApacheBench 在并发级别 1 下触发 1000 个请求(为了不损害单线程 Node 应用程序),结果如下:

Concurrency Level:      1
Time taken for tests:   10.377 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      3057000 bytes
HTML transferred:       2829000 bytes
Requests per second:    96.37 [#/sec] (mean)
Time per request:       10.377 [ms] (mean)
Time per request:       10.377 [ms] (mean, across all concurrent requests)
Transfer rate:          287.69 [Kbytes/sec] received

作为比较,下面是我的 PHP 代码:

<?php

    $hostname = <host>;
    $username = <user>;
    $password = <password>;
    $database = <database>;

    try {
        $db_handler = new PDO('mysql:host=' . $hostname . ';dbname=' . $database, $username, $password);
    } catch (PDOException $e) {
        throw new Exception('[ERROR] Unable to connect to the database.');
    }

    $sql = 'SELECT column_1, column_2 FROM table';
    $statement = $db_handler->prepare($sql, array(PDO::ATTR_CURSOR => PDO::CURSOR_FWDONLY));
    $statement->execute();
    $rows = array();
    while ($row = $statement->fetch(PDO::FETCH_ASSOC)){
        $rows[] = $row;
    }
    print json_encode($rows);

    $db_handler = null;

?>

ApacheBench 的结果:

Concurrency Level:      1
Time taken for tests:   6.726 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      3023000 bytes
HTML transferred:       2829000 bytes
Requests per second:    148.68 [#/sec] (mean)
Time per request:       6.726 [ms] (mean)
Time per request:       6.726 [ms] (mean, across all concurrent requests)
Transfer rate:          438.92 [Kbytes/sec] received

从上面的结果可以看出,PHP 比 NodeJS 快得多。如果触发更复杂的查询(差异可能是 20 倍,例如 20 毫秒与 400 毫秒),或者如果并发级别增加,则差异会更大。

我尝试向 Node 应用程序添加最多 4 个工作线程(我在有 4 个核心的 Raspberry Pi 2 上运行服务器),看看它是否有帮助,不幸的是它仍然与 PHP 中的结果不接近。你能告诉我我可能做错了什么吗?或者 NodeJS 对于我想要实现的目标来说并不是一个好的选择?

[已编辑]

非常感谢您的所有评论。似乎大多数人怀疑问题是由 NodeJS MySQL 驱动程序引起的。我还做了更多测试来确定情况是否如此,并且我意外地发现了一些非常有趣的东西。

通过在另一台 PC(Core 2 Duo E7200)上运行相同的 Node 应用程序,但在 Raspberry Pi 上连接到相同的 MySQL,结果实际上相当不错:

Concurrency Level:      1
Time taken for tests:   2.705 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      3057000 bytes
HTML transferred:       2829000 bytes
Requests per second:    369.71 [#/sec] (mean)
Time per request:       2.705 [ms] (mean)
Time per request:       2.705 [ms] (mean, across all concurrent requests)
Transfer rate:          1103.72 [Kbytes/sec] received

作为比较,我还在该 PC 上运行了 Apache 服务器,连接到 Raspberry Pi 上的相同 MySQL,结果如下:

Concurrency Level:      1
Time taken for tests:   6.297 seconds
Complete requests:      1000
Failed requests:        0
Total transferred:      3034000 bytes
HTML transferred:       2829000 bytes
Requests per second:    158.80 [#/sec] (mean)
Time per request:       6.297 [ms] (mean)
Time per request:       6.297 [ms] (mean, across all concurrent requests)
Transfer rate:          470.50 [Kbytes/sec] received

作为总结,以下是我迄今为止得到的结果。只有 Web 服务器部分不同,而数据库始终是 Raspberry Pi 上的 MySQL:

Server      Time Taken
Node (Pi)   10.337s
PHP (Pi)    6.726s
Node (PC)   2.705s
PHP (PC)    6.297s

PHP 的结果在两台服务器上似乎或多或少相同,而 NodeJS 的结果差异很大。根据上面的结果,在我看来 NodeJS 对 CPU 性能更敏感,或者换句话说 CPU 密集型? (我使用的NodeJS版本是v6.9.4,仅供参考)

php mysql node.js apache performance
2个回答
5
投票

使用 ApacheBench 在并发级别 1 下触发 1000 个请求(为了不损害单线程 Node 应用程序)

通过将并发限制为 1,您实际上剥夺了节点最大的优势,即异步 IO。即使node.js是单线程的,它也会在等待db.query调用时处理其他请求。

因为 Node 不使用系统线程,而是使用自己的轻量级调度程序,所以它可以比 Apache 更便宜地执行并发请求。 Apache 可以通过不同的方式配置来处理多个请求(例如,预分叉固定数量的进程或事件驱动的分叉),但是一旦并发请求达到一定数量,事情就会变慢,因为请求可能需要等待其他人要完成,即使其他人除了等待数据库什么也没做。

因此,总而言之,对于同步执行单个请求,PHP 可能更快;但是,一旦您有足够的请求,超出了 Apache 配置设置的限制,并且还受到计算机大小的影响,您应该会看到 Node.js 总体上更快。


0
投票

我尝试做一些类似的测试。

ab -n 10000 -c 10 http://localhost:8080/

ab -n 10000 -c 100 http://localhost:8080/

节点可能会因错误而崩溃

"Too many connections"
如果修改代码在查询后添加
con.end()
节点可能会因错误而崩溃
"PROTOCOL_SEQUENCE_TIMEOUT"
可能需要修改代码并进行更多测试。

P/S:php 没有错误。

ab -n 10000 -c 10000 http://localhost/Php03.php

© www.soinside.com 2019 - 2024. All rights reserved.