NodeJS比PHP慢得多?

CLD*_*Dev 13 php mysql apache performance node.js

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

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

但是,我遇到了一些性能问题,我正在试图找出问题所在.为了解决问题,我创建了一个最小的NodeJS应用程序,它运行针对MySQL的查询并返回50行数据作为JSON.以下是我的代码:

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.");
});
Run Code Online (Sandbox Code Playgroud)

通过使用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
Run Code Online (Sandbox Code Playgroud)

作为比较,下面是我在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;

?>
Run Code Online (Sandbox Code Playgroud)

而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
Run Code Online (Sandbox Code Playgroud)

从上面的结果可以看出,PHP比NodeJS快得多.如果触发更复杂的查询(差异可能是20次,如20ms vs 400ms),或者并发级别增加,则差异甚至更大.

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

[EDITED]

非常感谢你的所有评论.似乎大多数人怀疑这个问题是由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
Run Code Online (Sandbox Code Playgroud)

作为比较,我还在该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
Run Code Online (Sandbox Code Playgroud)

总结一下,下面是我到目前为止的结果.只有Web服务器部分不同,而数据库在Raspberry Pi上始终是MySQL:

Server      Time Taken
Node (Pi)   10.337s
PHP (Pi)    6.726s
Node (PC)   2.705s
PHP (PC)    6.297s
Run Code Online (Sandbox Code Playgroud)

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

小智 5

通过使用ApacheBench以并发级别1发出1000个请求(为了不使单线程Node应用程序不利)

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

因为节点没有使用系统线程,而是它自己的轻量级调度程序,它可以比Apache便宜得多的并发请求.Apache可以以不同的方式配置来处理多个请求(例如,预先分配固定数量的进程或事件驱动的分叉),但是一旦你有一定数量的并发请求,事情就会变慢,因为请求可能需要等待其他人要完成,即使其他人除了等待数据库之外什么都不做.

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