02-异步编程与性能优化

知识库
知识库文档
/tech-stacks/nodejs/tutorial/02-异步编程与性能优化.md

文档

Node.js 进阶篇:异步编程与性能优化

背景

Node.js 的异步模型是其性能核心。理解 Promise、async/await、Worker Threads 以及 Stream,是编写高性能 Node.js 应用的关键。

核心概念

1. Promise 链与 async/await

// 回调地狱 ❌
fs.readFile('a.txt', (err, dataA) => {
  fs.readFile('b.txt', (err, dataB) => {
    fs.readFile('c.txt', (err, dataC) => {
      console.log(dataA + dataB + dataC);
    });
  });
});

// Promise 链 ✅
Promise.all([
  fs.promises.readFile('a.txt'),
  fs.promises.readFile('b.txt'),
  fs.promises.readFile('c.txt'),
]).then(buffers => console.log(buffers.join('')));

// async/await 最优雅 ✅
const [a, b, c] = await Promise.all([
  fs.promises.readFile('a.txt'),
  fs.promises.readFile('b.txt'),
  fs.promises.readFile('c.txt'),
]);

2. Stream — 流式处理大数据

const fs = require('fs');
const zlib = require('zlib');

// 边读边压缩边写 — 内存占用恒定
fs.createReadStream('large.log')
  .pipe(zlib.createGzip())
  .pipe(fs.createWriteStream('large.log.gz'));

3. Worker Threads — 突破单线程限制

// main.js
const { Worker } = require('worker_threads');

function runCPUIntensiveTask(data) {
  return new Promise((resolve, reject) => {
    const worker = new Worker('./worker.js', { workerData: data });
    worker.on('message', resolve);
    worker.on('error', reject);
  });
}

// worker.js
const { parentPort, workerData } = require('worker_threads');
// 执行 CPU 密集运算
let result = fibonacci(workerData.n);
parentPort.postMessage(result);

4. Cluster — 利用多核 CPU

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

if (cluster.isPrimary) {
  os.cpus().forEach(() => cluster.fork());
  cluster.on('exit', (worker) => cluster.fork()); // 自动重启
} else {
  require('./app'); // 启动 Express 服务
}

性能优化检查清单

优化项 方法
数据库查询 使用连接池、添加索引、避免 N+1 查询
缓存 Redis 缓存热点数据、设置合理 TTL
压缩 启用 gzip/br 压缩响应
静态资源 使用 CDN 或 Nginx 反代
内存泄漏 使用 --inspect + Chrome DevTools 排查
事件循环阻塞 避免同步 I/O、大循环拆分为 setImmediate

分步操作:压测与排查

# 1. 使用 autocannon 压测
npm i -g autocannon
autocannon -c 100 -d 10 http://localhost:3000/users

# 2. 使用 clinic.js 诊断性能
npm i -g clinic
clinic doctor -- node app.js
# 然后运行 autocannon,分析生成的 HTML 报告

# 3. 查找耗时中间件
app.use((req, res, next) =>; {
  const start = Date.now();
  res.on('finish', () =>; {
    console.log(`${req.method} ${req.url} ${Date.now() - start}ms`);
  });
  next();
});

思考题

  1. Promise.allPromise.allSettled 有什么区别?什么场景用哪个?
  2. 为什么 Worker Threads 不适合处理大量 I/O 操作?
  3. Stream 的背压(backpressure)机制是如何工作的?

信息

路径
/tech-stacks/nodejs/tutorial/02-异步编程与性能优化.md
更新时间
2026/5/30