使用mysql池对node.js(cluster)的性能进行基准testing:Lighttpd + PHP?

编辑(2):现在使用db-mysql和generic-pool模块。 错误率大幅下降,徘徊在13%,但吞吐量仍然在100瑞士克/秒左右。

编辑(1):有人build议ORDER BY RAND()会导致MySQL变慢,我已经从查询中删除该子句。 Node.js现在徘徊在100 req / sec左右,但服务器仍报告“连接错误:连接太多”。

Node.js或Lighttpd与PHP?

你可能看到了许多“Hello World”的node.js基准testing,但是“hello world”testing,即使是那些每个请求延迟了2秒的testing,甚至都不能接近现实世界的产品使用情况。 我还使用node.js执行了“Hello World”testing的这些变体,并且看到吞吐量约为800 req / sec,错误率为0.01%。 但是,我决定进行一些比较现实的testing。

也许我的testing没有完成,很可能是node.js或我的testing代码真的是错误的,所以如果你是一个node.js专家,请帮我写一些更好的testing。 我的结果发表如下。 我使用Apache JMeter来进行testing。

testing用例和系统规格

testing非常简单。 用户数量的mysql查询是随机排列的。 第一个用户的用户名被检索和显示。 mysql数据库连接是通过一个unix套接字。 操作系统是FreeBSD 8+。 8GB的RAM。 英特尔至强四核2.x Ghz处理器。 我甚至在我遇到node.js之前调整了Lighttpdconfiguration。

Apache JMeter设置

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

加速期(以秒为单位):1

循环计数:10 这是每个用户的请求数量

Apache JMeter最终结果

标签|  #Samples | 平均|  Min | 最大| 标准。 开发。  | 错误%| 吞吐量|  KB / sec | 平均。 字节

 HTTP请求Lighttpd |  49918 |  2060ms |  29ms |  84790ms |  5524 |  19.47%|  583.3 / sec |  211.79 |  371.8

 HTTP请求Node.js |  13767 |  106569ms |  295ms |  292311ms |  91764 |  78.86%|  44.6 / sec |  79.16 |  1816

结果结论

Node.js是如此糟糕,我不得不提前停止testing。 [完全固定testing]

Node.js报告服务器上的“连接错误:连接太多”。 [ 修正 ]

大多数时候,Lighttpd的吞吐量约为1200瑞克/秒。

但是,node.js的吞吐量大约是29个/秒。 [现在在100req /秒]

这是我用于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中,select整个表并将其放入一个数组中。 在PHP中,你只parsing第一行。 所以你的表越大,节点越慢。 如果你使用mysqli_fetch_all做了一个类似的比较。 虽然db-mysql应该是快速的,但它不是非常全面的function,而且缺乏使这个公平比较的能力。 使用不同的node.js模块(如node-mysql-libmysqlclient)应该只允许您处理第一行。

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

所以不知何故,你的连接不会被重复用于不同的请求。 可能你已经有一个查询在每个连接上运行。

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

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

问题是从节点的一个进程到CPU的一个核心,PHP通过multithreading与所有四个核心进行扩展。 我想说的是,使用四核2.x GHz处理器,通过能够利用额外的资源,PHP肯定会比Node有更大的优势。

还有一个讨论提供了一些关于如何在多核上扩展节点的信息,但是这必须通过编码明确地完成。 再一次,纠正我,如果我错了,但我没有看到在上面的例子中的任何这样的代码。

我自己很新,但我希望这可以帮助你改善你的testing:)

你用PHP启用了APC吗?

你可以尝试启用持久连接与PHP? 例如

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

您不是在Node.js中使用10个最大的MySQL连接,而是通过PHP使用5000个最大的MySQL连接?

当你在任一系统上运行你的testing时,我会看看MySQL的“SHOW FULL PROCESSLIST”。

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

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

这是一个糟糕的基准,它应该是一个简单的“hello world”,因为成千上万的基准certificatenodejs是所有时间中速度最快的“hello world”服务器:D