NodeJS比PHP慢得多?

时间:2017-01-30 04:07:40

标签: php mysql node.js apache performance

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

  1. 提供一些静态文件(HTML / CSS /图像资源等)
  2. 查询数据库(仅选择并插入,不更新或删除)
  3. 但是,我遇到了一些性能问题,而我正试图找出问题所在。为了解决这个问题,我创建了一个最小的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.");
    });
    

    通过使用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次,比如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
    

    作为比较,我还在该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,仅供参考)

1 个答案:

答案 0 :(得分:5)

  

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

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

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

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