Nodejs 的压力测试

Nodejs 的压力测试

分别对三种情况进行了压力测试,程序是执行一条mysql语句 工具:ab 一共1000的请求,每秒100个并发 ,测试结果如下: 1、没做处理的

Concurrency Level: 100 Time taken for tests: 3.234 seconds Complete requests: 1000 Failed requests: 0 Write errors: 0 Total transferred: 299000 bytes HTML transferred: 224000 bytes Requests per second: 309.18 [#/sec] (mean) Time per request: 323.438 [ms] (mean) Time per request: 3.234 [ms] (mean, across all concurrent requests) Transfer rate: 90.28 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 0 2.5 0 16 Processing: 63 310 53.9 313 500 Waiting: 63 308 54.0 297 500 Total: 63 311 53.9 313 500 Percentage of the requests served within a certain time (ms) 50% 313 66% 313 75% 328 80% 344 90% 375 95% 406 98% 438 99% 469 100% 500 (longest request)

2、用了cluster 双核cpu

Concurrency Level: 100 Time taken for tests: 3.266 seconds Complete requests: 1000 Failed requests: 0 Write errors: 0 Total transferred: 299000 bytes HTML transferred: 224000 bytes Requests per second: 306.22 [#/sec] (mean) Time per request: 326.563 [ms] (mean) Time per request: 3.266 [ms] (mean, across all concurrent requests) Transfer rate: 89.41 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 1 2.8 0 16 Processing: 141 303 41.1 313 391 Waiting: 125 300 42.1 313 391 Total: 141 303 41.0 313 391 Percentage of the requests served within a certain time (ms) 50% 313 66% 313 75% 328 80% 328 90% 344 95% 359 98% 359 99% 375 100% 391 (longest request)

3、用了pool连接池 最大连接数100 30秒超时,每次请求后释放

Concurrency Level: 100 Time taken for tests: 4.969 seconds Complete requests: 1000 Failed requests: 0 Write errors: 0 Total transferred: 299000 bytes HTML transferred: 224000 bytes Requests per second: 201.26 [#/sec] (mean) Time per request: 496.875 [ms] (mean) Time per request: 4.969 [ms] (mean, across all concurrent requests) Transfer rate: 58.77 [Kbytes/sec] received Connection Times (ms) min mean[+/-sd] median max Connect: 0 1 2.9 0 16 Processing: 234 482 122.2 453 1000 Waiting: 109 371 119.7 344 891 Total: 234 482 122.2 453 1000 Percentage of the requests served within a certain time (ms) 50% 453 66% 469 75% 469 80% 500 90% 563 95% 859 98% 922 99% 984 100% 1000 (longest request)

为啥第二种与第一种几乎一样,第三种最差呢?


6 回复

Node.js 压力测试

在本篇博客中,我们将通过三种不同的方法对一个简单的 Node.js 应用进行压力测试。该应用的主要任务是执行一条 MySQL 查询。

工具

我们使用 ab(Apache Bench)工具来进行压力测试。ab 是一个简单而强大的命令行工具,用于对 HTTP 服务器进行基准测试。

测试环境

  • 每次测试共发送 1000 个请求。
  • 并发请求为每秒 100 个。

测试场景

  1. 未做任何优化
  2. 使用 cluster 模块以利用双核 CPU
  3. 使用 MySQL 连接池

测试结果

1. 未做处理的情况

Concurrency Level:      100
Time taken for tests:   3.234 seconds
Complete requests:      1000
Failed requests:        0
Write errors:           0
Requests per second:    309.18 [#/sec] (mean)
Time per request:       323.438 [ms] (mean)

2. 使用 cluster 模块

Concurrency Level:      100
Time taken for tests:   3.266 seconds
Complete requests:      1000
Failed requests:        0
Requests per second:    306.22 [#/sec] (mean)
Time per request:       326.563 [ms] (mean)

3. 使用 MySQL 连接池

Concurrency Level:      100
Time taken for tests:   4.969 seconds
Complete requests:      1000
Failed requests:        0
Requests per second:    201.26 [#/sec] (mean)
Time per request:       496.875 [ms] (mean)

分析

为什么第二种与第一种几乎一样?

在第二种情况下,我们使用了 cluster 模块来利用多核 CPU 的优势。然而,由于 Node.js 本身是单线程的事件驱动模型,cluster 模块主要用于在多个进程中分配工作负载,从而更好地利用多核 CPU。在这种简单的查询场景下,cluster 并没有显著提升性能,因为主要瓶颈可能并不在于 CPU 负载,而是数据库查询本身的性能。

为什么第三种情况表现最差?

在第三种情况下,我们使用了 MySQL 连接池。理论上,连接池应该能够提高性能,因为它减少了频繁创建和销毁数据库连接的开销。然而,在这种情况下,连接池反而增加了额外的开销,特别是在高并发情况下,可能会导致连接池中的连接等待时间增加,从而降低了整体性能。

示例代码

以下是一个简单的 Node.js 应用示例,展示了如何使用 clustermysql 连接池:

const mysql = require('mysql');
const cluster = require('cluster');

if (cluster.isMaster) {
  // Fork workers.
  for (let i = 0; i < 2; i++) {
    cluster.fork();
  }
} else {
  const pool = mysql.createPool({
    host: 'localhost',
    user: 'root',
    password: 'password',
    database: 'testdb',
    connectionLimit: 100,
    acquireTimeout: 30000
  });

  function queryDatabase() {
    pool.query('SELECT * FROM users', (err, results) => {
      if (err) throw err;
      console.log(results);
    });
  }

  setInterval(queryDatabase, 1000);
}

以上代码展示了如何使用 cluster 模块来利用多核 CPU,并使用 mysql 连接池来管理数据库连接。希望这些信息能帮助你更好地理解和优化 Node.js 应用的压力测试。


这个要看代码怎么写的,用了什么驱动,还有数据库是不是限制连接已经达到瓶劲了

就一条语句

_db.query('SELECT  id,title FROM `blog_article` ', function(err, results, fields){
		res.write(JSON.stringify(results));
		res.end();
	});

mysql设置的最大连接数为100

3种测试结果指向一个结论:测定的瓶颈在于mysql的IO读取。cluster对于减少mysql的io访问时间毫无帮助;每次请求后释放则需要重新连接mysql,增加mysql的io访问时间。

路过~

从你的测试结果来看,第一种情况(未做处理)和第二种情况(使用cluster模块)的性能非常接近,这可能是因为MySQL查询本身已经达到了数据库处理能力的瓶颈。而第三种情况(使用连接池)表现较差,可能是因为连接池本身的开销增加了请求的处理时间。

以下是一个简单的示例,展示如何使用ab工具进行压力测试,并提供一个简单的Node.js应用来测试MySQL连接池的效果:

示例代码

const express = require('express');
const mysql = require('mysql');
const pool = mysql.createPool({
  host: 'localhost',
  user: 'root',
  password: 'password',
  database: 'testdb',
  connectionLimit: 100,
  acquireTimeout: 30000
});

const app = express();

app.get('/', async (req, res) => {
  try {
    const connection = await new Promise((resolve, reject) => {
      pool.getConnection((err, conn) => {
        if (err) reject(err);
        else resolve(conn);
      });
    });

    const [rows] = await connection.query('SELECT * FROM users LIMIT 1');
    res.json(rows);
    connection.release(); // 释放连接到连接池
  } catch (error) {
    console.error(error);
    res.status(500).send('Database error');
  }
});

const PORT = process.env.PORT || 3000;
app.listen(PORT, () => {
  console.log(`Server running on port ${PORT}`);
});

解释

  1. 创建连接池:使用mysql.createPool创建一个连接池,设置最大连接数为100,超时时间为30秒。
  2. Express应用:创建一个简单的Express应用,处理GET请求并执行一条SQL查询。
  3. 释放连接:查询完成后,将连接释放回连接池以供其他请求使用。

压力测试命令

使用ab工具进行压力测试:

ab -n 1000 -c 100 http://localhost:3000/

分析

  • Cluster模块:如果你的Node.js应用是单线程的,那么使用cluster模块可以充分利用多核CPU,提高处理能力。
  • 连接池:连接池的主要目的是减少频繁创建和销毁数据库连接的开销。但如果连接池管理不当,反而会增加额外的开销。

通过调整连接池参数或优化数据库查询,可以进一步提高性能。

回到顶部