后端性能:Node.js性能优化与调优
大家好,我是欧阳瑞(Rich Own)。今天想和大家聊聊Node.js性能优化这个重要话题。作为一个全栈开发者,后端性能直接影响应用的吞吐量和响应时间。今天就来分享一下Node.js性能优化的最佳实践。
Node.js性能概述
常见性能瓶颈
| 瓶颈 | 说明 |
|---|---|
| CPU密集型任务 | 阻塞事件循环 |
| 内存泄漏 | 内存持续增长 |
| I/O操作 | 数据库查询慢 |
| 同步操作 | 阻塞主线程 |
性能指标
| 指标 | 说明 | 目标值 |
|---|---|---|
| QPS | 每秒请求数 | 根据业务需求 |
| 响应时间 | 请求响应耗时 | < 100ms |
| 内存使用 | 进程内存占用 | 稳定在固定范围 |
| CPU使用率 | 处理器占用率 | < 70% |
CPU优化
避免阻塞事件循环
javascript
// 不好的做法:同步密集计算
function fibonacci(n) {
if (n <= 1) return n;
return fibonacci(n - 1) + fibonacci(n - 2);
}
app.get('/fib/:n', (req, res) => {
const result = fibonacci(parseInt(req.params.n)); // 阻塞事件循环
res.send({ result });
});
// 好的做法:使用Worker线程
const { Worker, isMainThread, parentPort } = require('worker_threads');
if (isMainThread) {
app.get('/fib/:n', (req, res) => {
const worker = new Worker(__filename);
worker.postMessage(parseInt(req.params.n));
worker.on('message', (result) => {
res.send({ result });
});
});
} else {
parentPort.on('message', (n) => {
const result = fibonacci(n);
parentPort.postMessage(result);
});
}
使用集群模式
javascript
const cluster = require('cluster');
const numCPUs = require('os').cpus().length;
if (cluster.isPrimary) {
console.log(`Primary ${process.pid} is running`);
for (let i = 0; i < numCPUs; i++) {
cluster.fork();
}
cluster.on('exit', (worker) => {
console.log(`Worker ${worker.process.pid} died`);
cluster.fork();
});
} else {
const express = require('express');
const app = express();
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.listen(3000);
console.log(`Worker ${process.pid} started`);
}
内存优化
内存泄漏检测
javascript
// 使用heapdump
const heapdump = require('heapdump');
setInterval(() => {
if (process.memoryUsage().heapUsed > 100 * 1024 * 1024) {
heapdump.writeSnapshot(`heap-${Date.now()}.heapsnapshot`);
}
}, 5000);
避免内存泄漏
javascript
// 不好的做法:全局变量累积
const cache = {};
function processRequest(data) {
const key = generateKey(data);
cache[key] = data; // 永不清理,内存持续增长
}
// 好的做法:使用LRU缓存
const LRU = require('lru-cache');
const cache = new LRU({
max: 1000,
ttl: 60 * 1000 // 1分钟过期
});
function processRequest(data) {
const key = generateKey(data);
cache.set(key, data);
}
I/O优化
数据库连接池
javascript
// 使用连接池
const mysql = require('mysql2/promise');
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
password: 'password',
database: 'mydb',
waitForConnections: true,
connectionLimit: 10,
queueLimit: 0
});
async function query(sql, params) {
const connection = await pool.getConnection();
try {
const [rows] = await connection.execute(sql, params);
return rows;
} finally {
connection.release();
}
}
批量操作
javascript
// 不好的做法:循环查询
async function processUsers(userIds) {
for (const id of userIds) {
await db.query('SELECT * FROM users WHERE id = ?', [id]);
}
}
// 好的做法:批量查询
async function processUsers(userIds) {
const placeholders = userIds.map(() => '?').join(',');
const users = await db.query(
`SELECT * FROM users WHERE id IN (${placeholders})`,
userIds
);
return users;
}
实战案例:性能监控
javascript
const express = require('express');
const app = express();
// 响应时间中间件
app.use((req, res, next) => {
const start = Date.now();
res.on('finish', () => {
const duration = Date.now() - start;
console.log(`${req.method} ${req.path} ${duration}ms`);
// 记录慢请求
if (duration > 500) {
console.warn(`Slow request: ${req.method} ${req.path} ${duration}ms`);
}
});
next();
});
// 内存监控
setInterval(() => {
const memUsage = process.memoryUsage();
console.log(`Memory: ${(memUsage.heapUsed / 1024 / 1024).toFixed(2)} MB`);
}, 5000);
app.listen(3000);
最佳实践
1. 使用异步API
javascript
// 不好的做法:同步读取文件
const fs = require('fs');
const data = fs.readFileSync('file.txt'); // 阻塞
// 好的做法:异步读取文件
const fs = require('fs').promises;
const data = await fs.readFile('file.txt'); // 非阻塞
2. 使用流式处理
javascript
// 处理大文件
const fs = require('fs');
const zlib = require('zlib');
const readStream = fs.createReadStream('large-file.txt');
const writeStream = fs.createWriteStream('large-file.txt.gz');
const gzip = zlib.createGzip();
readStream.pipe(gzip).pipe(writeStream);
总结
Node.js性能优化需要从多个方面入手。通过优化CPU使用、内存管理和I/O操作,可以显著提升应用性能。
我的鬃狮蜥Hash对性能优化也有自己的理解------它总是选择最有效的路径捕捉蟋蟀,这也许就是自然界的"性能优化"吧!
如果你对Node.js性能优化有任何问题,欢迎留言交流!我是欧阳瑞,极客之路,永无止境!
技术栈:Node.js · 性能优化 · 后端调优