使用mysql连接池测试node.js(集群)的性能:与Lighttpd + PHP相比如何?

7

编辑(2):现在使用db-mysql和generic-pool模块。错误率显著降低,但吞吐量仍约为100 req/sec。

编辑(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的RAM。 Intel Xeon四核2.x GHz处理器。在我遇到node.js之前,我对Lighttpd配置进行了一些调整。

Apache JMeter设置

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

渐进周期(秒):1

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

Apache JMeter最终结果

标签                   | #样本| 平均值   | 最小值 | 最大值    | 标准偏差 | 错误% | 吞吐量 | 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太糟糕了,我不得不提前停止测试。 [已修复完全测试]

Node.js在服务器上报告“CONNECTION error:Too many connections”。[已修复]

大多数情况下,Lighttpd的吞吐量约为1200 req/sec。

然而,node.js 的吞吐量约为29个请求/秒。[已修复,现在为100个请求/秒]

这是我在 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';
  }
?>

3
在MySQL中,ORDER BY RAND()会变慢,如果你的数据库导致了一些延迟,这将不是一个公平的测试。 - fire
1
我将执行相同的测试,但不使用 ORDER BY RAND()。由于两者都在本地访问完全相同的数据库,我认为这是一个公平的测试。 - einthusan
在Node中,您不应该为每个请求重新连接到数据库。 - thejh
2
使用一个池,例如这个:https://github.com/coopernurse/node-pool - thejh
由于这是FreeBSD,应该是“limits”而不是“ulimit”。无论如何,我现在正在使用@thejh提到的generic-pool进行测试。当数据库池连接死亡等情况发生时,它也会被销毁。如果我的代码有误,请纠正我。谢谢。 - einthusan
显示剩余4条评论
7个回答

6

这是一个糟糕的基准比较。在node.js中,您选择整个表格并将其放入数组中。而在php中,您只解析第一行。因此,您的表格越大,node看起来就越慢。如果您让php使用mysqli_fetch_all,那么它将是一个类似的比较。虽然db-mysql应该很快,但它缺乏使这成为公平比较的能力。使用不同的node.js模块,如node-mysql-libmysqlclient,应该允许您仅处理第一行。


4

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

因此,你的连接没有被重复使用于不同的请求。可能每个连接上已经有一个查询在运行。

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


2
如果我说错了,请纠正我,但我感觉你忽略了一些东西:Node使用单个进程来处理每个请求(并通过事件处理它们,仍然是同一个进程),而PHP为每个请求获取一个新的进程(线程)。
问题在于,来自Node的一个进程会固定在CPU的一个核心上,而PHP通过多线程可以与所有四个核心进行扩展。我认为,在四核2.x GHz处理器上,PHP肯定比Node更有优势,只是因为能够利用额外的资源。
还有另外一个讨论提供了一些关于如何将Node扩展到多个核心的信息,但这必须通过编码明确完成。再次纠正我,但我没有在上面的示例中看到任何这样的代码。
我对Node也很陌生,但我希望这可以帮助您改善您的测试 :)

1
你是否已经在PHP中启用了APC?
你可以尝试启用PHP的持久连接,例如:
$conn = new mysqli('p:localhost', 'root', 'password', 'v3edb2011');

0
有一件事需要考虑,那就是驱动程序 - 数据库性能很大程度上取决于你使用的具体驱动程序。最受欢迎且最活跃维护的MySQL驱动程序是https://github.com/felixge/node-mysql。使用它可能会得到不同的结果。
但是,如果你被限制在100个连接上,听起来好像连接没有被正确关闭。我建议在连接池销毁事件中添加一个console.log语句,以确保它真的执行了。

0

你在 Node.js 中最多使用了 10 个 MySQL 连接,而通过 PHP 最多使用了 5000 个 MySQL 连接,是吗?

当你在任一系统上运行测试时,我建议查看 MySQL 的 "SHOW FULL PROCESSLIST"。


-1

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


4
这更适合作为一条评论。 - davepmiller

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接