Node.js 性能优化指南
🎯 概述
Node.js 是一个基于Chrome V8引擎的JavaScript运行时,广泛用于构建高性能的网络应用。本文将分享Node.js性能优化的实用技巧。
📚 核心优化策略
1. 异步编程最佳实践
javascript
// ❌ 错误:阻塞式操作
function processData() {
const data = fs.readFileSync('large-file.txt', 'utf8')
const processed = data.split('\n').map(line => line.toUpperCase())
return processed
}
// ✅ 正确:异步操作
async function processData() {
try {
const data = await fs.promises.readFile('large-file.txt', 'utf8')
const processed = data.split('\n').map(line => line.toUpperCase())
return processed
} catch (error) {
console.error('Error processing file:', error)
throw error
}
}2. 内存管理
javascript
// 使用流处理大文件
const fs = require('fs')
const { Transform } = require('stream')
function processLargeFile(inputPath, outputPath) {
const readStream = fs.createReadStream(inputPath)
const writeStream = fs.createWriteStream(outputPath)
const transformStream = new Transform({
transform(chunk, encoding, callback) {
const processed = chunk.toString().toUpperCase()
callback(null, processed)
}
})
readStream
.pipe(transformStream)
.pipe(writeStream)
.on('error', (error) => {
console.error('Stream error:', error)
})
.on('finish', () => {
console.log('File processing completed')
})
}🚀 性能优化技巧
1. 缓存策略
javascript
const NodeCache = require('node-cache')
const cache = new NodeCache({ stdTTL: 600 }) // 10分钟缓存
async function getExpensiveData(key) {
// 先检查缓存
const cached = cache.get(key)
if (cached) {
return cached
}
// 缓存未命中,从数据库获取
const data = await database.query('SELECT * FROM expensive_table WHERE key = ?', [key])
// 存入缓存
cache.set(key, data)
return data
}2. 连接池管理
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 queryDatabase(sql, params) {
const connection = await pool.getConnection()
try {
const [rows] = await connection.execute(sql, params)
return rows
} finally {
connection.release()
}
}3. 集群模式
javascript
const cluster = require('cluster')
const numCPUs = require('os').cpus().length
if (cluster.isMaster) {
console.log(`Master ${process.pid} is running`)
// 创建工作进程
for (let i = 0; i < numCPUs; i++) {
cluster.fork()
}
cluster.on('exit', (worker, code, signal) => {
console.log(`Worker ${worker.process.pid} died`)
cluster.fork() // 重启工作进程
})
} else {
// 工作进程
const express = require('express')
const app = express()
app.get('/', (req, res) => {
res.json({ message: 'Hello from worker ' + process.pid })
})
app.listen(3000, () => {
console.log(`Worker ${process.pid} started`)
})
}🛠️ 监控和调试
1. 性能监控
javascript
const perf_hooks = require('perf_hooks')
// 监控函数执行时间
function monitorPerformance(fn) {
return async function(...args) {
const start = perf_hooks.performance.now()
try {
const result = await fn.apply(this, args)
const end = perf_hooks.performance.now()
console.log(`Function ${fn.name} took ${end - start} milliseconds`)
return result
} catch (error) {
const end = perf_hooks.performance.now()
console.log(`Function ${fn.name} failed after ${end - start} milliseconds`)
throw error
}
}
}
// 使用示例
const monitoredFunction = monitorPerformance(async (data) => {
// 一些异步操作
await new Promise(resolve => setTimeout(resolve, 1000))
return data
})2. 内存监控
javascript
function logMemoryUsage() {
const used = process.memoryUsage()
console.log('Memory Usage:')
console.log(`RSS: ${Math.round(used.rss / 1024 / 1024)} MB`)
console.log(`Heap Total: ${Math.round(used.heapTotal / 1024 / 1024)} MB`)
console.log(`Heap Used: ${Math.round(used.heapUsed / 1024 / 1024)} MB`)
console.log(`External: ${Math.round(used.external / 1024 / 1024)} MB`)
}
// 定期监控内存使用
setInterval(logMemoryUsage, 30000) // 每30秒📦 项目配置
1. Package.json 优化
json
{
"name": "my-node-app",
"version": "1.0.0",
"main": "src/index.js",
"scripts": {
"start": "node src/index.js",
"dev": "nodemon src/index.js",
"test": "jest",
"build": "webpack --mode production",
"pm2:start": "pm2 start ecosystem.config.js",
"pm2:stop": "pm2 stop all"
},
"engines": {
"node": ">=16.0.0",
"npm": ">=8.0.0"
}
}2. PM2 配置
javascript
// ecosystem.config.js
module.exports = {
apps: [{
name: 'my-app',
script: 'src/index.js',
instances: 'max',
exec_mode: 'cluster',
env: {
NODE_ENV: 'development'
},
env_production: {
NODE_ENV: 'production'
},
watch: false,
max_memory_restart: '1G',
error_file: './logs/err.log',
out_file: './logs/out.log',
log_file: './logs/combined.log',
time: true
}]
}🧪 测试
1. 单元测试
javascript
const request = require('supertest')
const app = require('../src/app')
describe('API Tests', () => {
test('GET /api/users should return users', async () => {
const response = await request(app)
.get('/api/users')
.expect(200)
expect(response.body).toHaveProperty('users')
expect(Array.isArray(response.body.users)).toBe(true)
})
test('POST /api/users should create user', async () => {
const userData = {
name: 'John Doe',
email: 'john@example.com'
}
const response = await request(app)
.post('/api/users')
.send(userData)
.expect(201)
expect(response.body).toHaveProperty('id')
expect(response.body.name).toBe(userData.name)
})
})2. 压力测试
javascript
const autocannon = require('autocannon')
async function runLoadTest() {
const result = await autocannon({
url: 'http://localhost:3000',
connections: 100, // 并发连接数
duration: 10, // 测试持续时间(秒)
requests: [
{
method: 'GET',
path: '/api/users'
}
]
})
console.log('Load Test Results:')
console.log(`Requests: ${result.requests.total}`)
console.log(`Duration: ${result.duration}ms`)
console.log(`Throughput: ${result.throughput} req/sec`)
console.log(`Latency: ${result.latency.average}ms`)
}
runLoadTest()🎯 最佳实践
1. 错误处理
javascript
// 全局错误处理
process.on('uncaughtException', (error) => {
console.error('Uncaught Exception:', error)
process.exit(1)
})
process.on('unhandledRejection', (reason, promise) => {
console.error('Unhandled Rejection at:', promise, 'reason:', reason)
process.exit(1)
})
// 异步错误处理
async function safeAsyncOperation() {
try {
const result = await riskyOperation()
return result
} catch (error) {
console.error('Operation failed:', error)
// 记录错误但不中断程序
return null
}
}2. 安全配置
javascript
const helmet = require('helmet')
const rateLimit = require('express-rate-limit')
// 安全头设置
app.use(helmet())
// 速率限制
const limiter = rateLimit({
windowMs: 15 * 60 * 1000, // 15分钟
max: 100 // 限制每个IP 15分钟内最多100个请求
})
app.use(limiter)
// CORS配置
app.use(cors({
origin: process.env.ALLOWED_ORIGINS?.split(',') || ['http://localhost:3000'],
credentials: true
}))Node.js 让后端开发更高效! 🚀