⚠️ Alpha内测版本警告:此为早期内部构建版本,尚不完整且可能存在错误,欢迎大家提Issue反馈问题或建议
Skip to content

10.5.4 性能瓶颈在哪——性能分析:响应时间与资源使用监控

用户说"慢",你要能说出具体慢在哪。

性能指标

用户体验指标

指标说明目标值
TTFB首字节时间< 200ms
FCP首次内容绘制< 1.8s
LCP最大内容绘制< 2.5s
TTI可交互时间< 3.8s

服务端指标

指标说明目标值
响应时间API 平均响应时间< 200ms
P95 延迟95% 请求的最大延迟< 500ms
P99 延迟99% 请求的最大延迟< 1s
吞吐量每秒处理请求数根据业务

响应时间监控

请求计时中间件

typescript
// NestJS 中间件
@Injectable()
export class TimingMiddleware implements NestMiddleware {
  use(req: Request, res: Response, next: NextFunction) {
    const start = Date.now();
    
    res.on('finish', () => {
      const duration = Date.now() - start;
      
      console.log(JSON.stringify({
        level: 'info',
        event: 'request_completed',
        method: req.method,
        path: req.path,
        status: res.statusCode,
        duration,
        slow: duration > 1000,  // 标记慢请求
      }));
      
      // 慢请求告警
      if (duration > 3000) {
        this.alertSlowRequest(req.path, duration);
      }
    });
    
    next();
  }
}

数据库查询监控

typescript
// Prisma 查询日志
const prisma = new PrismaClient({
  log: [
    { emit: 'event', level: 'query' },
  ],
});

prisma.$on('query', (e) => {
  if (e.duration > 100) {  // 慢查询阈值 100ms
    console.log(JSON.stringify({
      level: 'warn',
      event: 'slow_query',
      query: e.query,
      params: e.params,
      duration: e.duration,
    }));
  }
});

资源使用监控

内存监控

typescript
// 定期记录内存使用
setInterval(() => {
  const usage = process.memoryUsage();
  
  console.log(JSON.stringify({
    level: 'info',
    event: 'memory_usage',
    heapUsed: Math.round(usage.heapUsed / 1024 / 1024),  // MB
    heapTotal: Math.round(usage.heapTotal / 1024 / 1024),
    rss: Math.round(usage.rss / 1024 / 1024),
  }));
  
  // 内存泄漏警告
  if (usage.heapUsed > 500 * 1024 * 1024) {  // > 500MB
    console.warn('High memory usage detected');
  }
}, 60000);  // 每分钟

CPU 监控

typescript
import * as os from 'os';

function getCpuUsage() {
  const cpus = os.cpus();
  let totalIdle = 0, totalTick = 0;
  
  cpus.forEach(cpu => {
    for (const type in cpu.times) {
      totalTick += cpu.times[type];
    }
    totalIdle += cpu.times.idle;
  });
  
  return 1 - totalIdle / totalTick;
}

性能分析工具

Node.js 内置工具

bash
# 启动时开启性能分析
node --prof app.js

# 生成可读报告
node --prof-process isolate-*.log > profile.txt

Chrome DevTools

typescript
// 在开发环境启用调试
if (process.env.NODE_ENV === 'development') {
  require('inspector').open(9229, 'localhost', true);
}

火焰图

bash
# 使用 0x 生成火焰图
npx 0x app.js

# 打开生成的 HTML 文件查看火焰图

常见性能问题

N+1 查询问题

typescript
// 问题代码 - N+1 查询
const users = await prisma.user.findMany();
for (const user of users) {
  const orders = await prisma.order.findMany({
    where: { userId: user.id }
  });
}

// 优化后 - 使用 include
const users = await prisma.user.findMany({
  include: { orders: true }
});

内存泄漏

typescript
// 问题代码 - 事件监听器泄漏
class Service {
  constructor() {
    eventEmitter.on('data', this.handleData);  // 每次实例化都添加
  }
}

// 优化后 - 清理监听器
class Service {
  constructor() {
    eventEmitter.on('data', this.handleData);
  }
  
  destroy() {
    eventEmitter.off('data', this.handleData);
  }
}

同步阻塞

typescript
// 问题代码 - 同步文件操作
const data = fs.readFileSync('large-file.txt');

// 优化后 - 异步操作
const data = await fs.promises.readFile('large-file.txt');

性能优化清单

数据库层

  • [ ] 添加必要的索引
  • [ ] 使用 include 代替多次查询
  • [ ] 分页查询大数据集
  • [ ] 使用 Redis 缓存热点数据

应用层

  • [ ] 启用 Gzip 压缩
  • [ ] 使用连接池
  • [ ] 避免同步操作
  • [ ] 优化大循环

网络层

  • [ ] 使用 CDN
  • [ ] 启用 HTTP/2
  • [ ] 合理设置缓存头
  • [ ] 图片压缩/WebP

压力测试

使用 k6

javascript
// load-test.js
import http from 'k6/http';
import { check, sleep } from 'k6';

export const options = {
  vus: 100,         // 100 个虚拟用户
  duration: '30s',  // 持续 30 秒
};

export default function() {
  const res = http.get('http://localhost:3000/api/health');
  
  check(res, {
    'status is 200': (r) => r.status === 200,
    'response time < 200ms': (r) => r.timings.duration < 200,
  });
  
  sleep(1);
}
bash
# 运行测试
k6 run load-test.js

使用 wrk

bash
# 简单压测
wrk -t12 -c400 -d30s http://localhost:3000/api/health

# 输出示例
Running 30s test @ http://localhost:3000/api/health
  12 threads and 400 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    50ms    10ms    200ms   85%
    Req/Sec   500      50       600    90%
  Requests/sec: 6000

性能基准

规模预期 QPS响应时间
小型项目100-500< 200ms
中型项目500-2000< 100ms
大型项目2000+< 50ms

常见问题

问题可能原因解决方案
响应时间波动大GC 暂停/慢查询优化内存使用/添加索引
CPU 持续高密集计算/死循环火焰图分析定位
内存持续增长内存泄漏堆快照分析
偶发超时连接池耗尽增加连接池大小