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

ein*_*san 7 php mysqli lighttpd node.js

编辑(2):现在使用db-mysql和generic-pool模块.错误率显着下降,徘徊在13%,但吞吐量仍然在100 req/sec左右.

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

使用PHP的Node.js或Lighttpd?

你可能看到了很多"Hello World"对node.js进行基准测试......但是"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结果

Label                  | # Samples | Average  | Min   | Max      | Std. Dev. | Error % | Throughput | KB/sec | Avg. Bytes

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

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

结果结论

Node.js太糟糕了我不得不提前停止测试.[ 已完全修复测试]

Node.js报告服务器上的"连接错误:连接太多".[ 固定 ]

大多数时候,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);
Run Code Online (Sandbox Code Playgroud)

这是我用于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';
  }
?>
Run Code Online (Sandbox Code Playgroud)

小智 5

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


Len*_*nie 4

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

因此,不知何故,您的连接不会被重复用于不同的请求。也许您已经在每个连接上运行一个查询。

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