跳到主要内容

服务端性能优化

问题

服务端性能优化有哪些常见手段?如何定位性能瓶颈?

答案

性能优化全景

常见瓶颈与优化

1. N+1 查询问题

n-plus-one.ts
// ❌ N+1 问题:查询 100 个用户,每个用户再查一次订单 = 101 条 SQL
const users = await db.user.findMany();
for (const user of users) {
user.orders = await db.order.findMany({ where: { userId: user.id } });
}

// ✅ 批量查询:只需 2 条 SQL
const users = await db.user.findMany();
const userIds = users.map(u => u.id);
const orders = await db.order.findMany({ where: { userId: { in: userIds } } });
const orderMap = groupBy(orders, 'userId');
users.forEach(user => { user.orders = orderMap[user.id] || []; });

// ✅ ORM 的 include/eager loading
const users = await prisma.user.findMany({
include: { orders: true },
});

2. 连接池配置

connection-pool.ts
// 数据库连接池
const pool = mysql.createPool({
host: 'localhost',
user: 'root',
database: 'mydb',
connectionLimit: 20, // 最大连接数
waitForConnections: true, // 连接池满时等待
queueLimit: 0, // 排队限制
});

// 连接池大小建议:connections = (CPU 核心数 * 2) + 磁盘数
// 一台 4 核机器:约 10 个连接

3. 异步处理

async-processing.ts
// ❌ 同步处理(接口响应慢)
app.post('/api/orders', async (req, res) => {
const order = await createOrder(req.body);
await sendEmail(order); // 等 500ms
await sendSMS(order); // 等 300ms
await updateInventory(order); // 等 200ms
res.json(order); // 总共 1s+
});

// ✅ 异步处理(接口快速返回)
app.post('/api/orders', async (req, res) => {
const order = await createOrder(req.body);

// 异步任务丢入消息队列
await queue.add('send-email', order);
await queue.add('send-sms', order);
await queue.add('update-inventory', order);

res.json(order); // 快速返回
});

压力测试

# 使用 autocannon (Node.js)
npx autocannon -c 100 -d 30 http://localhost:3000/api/users
# -c 100: 100 个并发连接
# -d 30: 持续 30 秒

# 使用 wrk
wrk -t12 -c400 -d30s http://localhost:3000/api/users

常见面试问题

Q1: 一个接口响应很慢,怎么排查?

答案

  1. 查看日志:请求各阶段耗时
  2. 检查数据库:慢查询日志(EXPLAIN 分析)
  3. 检查缓存:是否未命中
  4. 检查网络:服务间调用延迟
  5. 检查资源:CPU、内存、磁盘 I/O

Q2: 如何应对高并发?

答案

  1. 缓存:减少数据库访问
  2. 异步:非核心逻辑异步处理
  3. 限流:保护下游服务
  4. 水平扩展:增加服务实例 + 负载均衡
  5. 数据库优化:读写分离、索引优化

Q3: QPS 和 TPS 的区别?

答案

  • QPS(Queries Per Second):每秒查询数,衡量读性能
  • TPS(Transactions Per Second):每秒事务数,衡量写性能
  • 一个 TPS 可能包含多个 QPS

Q4: 如何设置合理的超时时间?

答案

  • 数据库查询:3-5 秒
  • 内部服务调用:5-10 秒
  • 外部 API 调用:10-30 秒
  • 级联超时:上游超时 > 下游超时,避免下游还在跑但上游已经超时返回了

相关链接