使用mysql池对node.js(集群)性能进行基准测试:Lighttpd + PHP


Benchmarking Performance of node.js (cluster) with mysql pools : Lighttpd + PHP?

Edit(2):现在使用db-mysql与泛型池模块。错误率已经显著下降,徘徊在13%,但吞吐量仍然在100 req/sec左右。

Edit(1):在有人建议ORDER BY RAND()会导致MySQL变慢之后,我从查询中删除了该子句。Node.js现在徘徊在100 req/sec左右,但服务器仍然报告"CONNECTION error: Too many connections"。

Node.js或Lighttpd与PHP?

你可能看过很多node.js的"Hello World"基准测试…但是"hello world"测试,即使是那些每个请求延迟2秒的测试,也无法接近真实世界的生产使用情况。我还使用node.js执行了这些"Hello World"的变体测试,发现吞吐量约为800 req/sec,错误率为0.01%。然而,我决定做一些更现实的测试。

也许我的测试不完整,很可能是node.js或我的测试代码真的有问题,所以如果你是node.js专家,请帮助我写一些更好的测试。我的研究结果发表在下面。我使用Apache JMeter进行测试。

测试用例和系统规格

这个测试非常简单。mysql查询的用户数量是随机排序的。检索并显示第一个用户的用户名。mysql数据库连接是通过unix套接字进行的。操作系统为FreeBSD 8+。8GB内存。英特尔至强四酷睿2。x Ghz处理器。在遇到node.js之前,我稍微调整了一下Lighttpd配置。

Apache JMeter Settings

线程数(用户):5000 我认为这是并发连接数

上升周期(秒):1

Loop Count: 10 这是每个用户的请求数

Apache JMeter End Results

<>之前标签| # Samples | Average | Min | Max | Std. Dev. | Error % | Throughput | KB/sec | Avg. BytesHTTP请求Lighttpd | 49918 | 2060ms | 29ms | 84790ms | 5524 | 19.47% | 583.3/秒| 211.79 | 371.8HTTP请求Node.js | 13767 | 106569ms | 295ms | 292311ms | 91764 | 78.86% | 44.6/sec | 79.16 | 1816之前

结果结论

Node.js是如此糟糕,我不得不提前停止测试。[修复已完全测试]

Node.js报告"CONNECTION error: Too many connections"。( ]

大多数时候,Lighttpd的吞吐量约为1200 req/sec。

然而,node.js的吞吐量约为29 req/sec。[修正现在为100req/sec]

这是我用于node.js(使用MySQL池)的代码

var cluster = require('cluster'), http = require('http'), mysql = require('db-mysql'), generic_pool = require('generic-pool');
var pool = generic_pool.Pool({
    name: 'mysql',
    max: 10,
    create: function(callback) {
        new mysql.Database({
            socket: "/tmp/mysql.sock",
            user: 'root',
            password: 'password',
            database: 'v3edb2011'
        }).connect(function(err, server) {
            callback(err, this);
        });
    },
        destroy: function(db) {
        db.disconnect();
    }
});
var server = http.createServer(function(request, response) {  
    response.writeHead(200, {"Content-Type": "text/html"});  
    pool.acquire(function(err, db) {
        if (err) {
            return response.end("CONNECTION error: " + err);
        }
        db.query('SELECT * FROM tb_users').execute(function(err, rows, columns) {
            pool.release(db);
            if (err) {
                return response.end("QUERY ERROR: " + err);
            }
            response.write(rows.length + ' ROWS found using node.js<br />');
            response.end(rows[0]["username"]);
        });
    });   
});
cluster(server)
  .set('workers', 5)
  .listen(8080);

这是我用于PHP (Lighttpd + FastCGI)的代码

<?php
  $conn = new mysqli('localhost', 'root', 'password', 'v3edb2011');
  if($conn) {
    $result = $conn->query('SELECT * FROM tb_users ORDER BY RAND()');
    if($result) {
      echo ($result->num_rows).' ROWS found using Lighttpd + PHP (FastCGI)<br />';
      $row = $result->fetch_assoc();
      echo $row['username'];
    } else {
      echo 'Error : DB Query';
    }
  } else {
    echo 'Error : DB Connection';
  }
?>

这是一个糟糕的基准比较。在node.js中,选择整个表并将其放入数组中。在php中,您只解析第一行。所以表越大,节点看起来就越慢。如果你让php使用mysqli_fetch_all,这将是一个类似的比较。虽然db-mysql被认为是快速的,但它并不是非常完整的功能,缺乏进行公平比较的能力。使用不同的node.js模块,如node-mysql-libmysqlclient,应该允许你只处理第一行。

100是MySQL默认设置的最大连接数。

所以你的连接没有被不同的请求重用。可能您已经在每个连接上运行了一个查询。

也许你正在使用的nodejs MySQL库不会在同一个MySQL连接上排队查询,而是尝试打开另一个连接并失败。

如果我错了请纠正我,但我觉得你忽略了一些东西:Node使用单个进程来处理每个请求(并通过事件处理它们,仍然是相同的进程),而php为每个请求获得一个新的进程(线程)。

这样做的问题是,来自node的一个进程粘在CPU的一个核心上,PHP通过多线程扩展到所有四个核心。我想说的是四核2。如果使用x GHz的处理器,PHP肯定会比Node有明显的优势,因为它能够利用额外的资源。

还有另一个讨论给出了一些关于如何在多核上扩展Node的信息,但这必须通过编码显式地完成。再一次,如果我错了,请纠正我,但我在上面的例子中没有看到任何这样的代码。

我自己对Node很陌生,但我希望这能帮助你改进你的测试:)

你是否启用了APC与PHP?

你可以尝试在PHP中启用持久连接吗?例如

$conn = new mysqli('p:localhost', 'root', 'password', 'v3edb2011');

你不是在Node.js中使用10个最大MySQL连接,而在PHP中使用5000个最大MySQL连接吗?

当你在任何一个系统上运行测试时,我会看一下MySQL的"SHOW FULL PROCESSLIST"。

需要考虑的一件事是驱动程序-数据库的性能可能与您正在使用的特定驱动程序密切相关。最流行的mysql驱动程序和最积极维护的是https://github.com/felixge/node-mysql。可能会得到不同的结果。

但是如果你被卡在100个连接上,听起来像是连接没有正确关闭。我可能会在池的destroy事件中添加一条console.log语句,以确保它确实在执行。

这是一个糟糕的基准测试,它应该是一个简单的"hello world",因为成千上万的基准测试证明nodejs是有史以来最快的"hello world"服务器:D