性能优化 #
一、性能概述 #
Fastify本身就是高性能框架,但通过合理配置可以进一步提升性能。
1.1 性能优势 #
| 优势 | 说明 |
|---|---|
| 高效路由 | 基于radix tree的路由匹配 |
| Schema验证 | fast-json-stringify加速序列化 |
| 低开销日志 | Pino日志库 |
| 异步优化 | 原生async/await支持 |
1.2 性能指标 #
javascript
fastify.addHook('onRequest', async (request, reply) => {
request.startTime = Date.now()
})
fastify.addHook('onResponse', async (request, reply) => {
const duration = Date.now() - request.startTime
console.log(`Request took ${duration}ms`)
})
二、基础优化 #
2.1 禁用不必要的功能 #
javascript
const fastify = require('fastify')({
logger: false,
disableRequestLogging: true,
ignoreTrailingSlash: true
})
2.2 优化日志配置 #
javascript
const fastify = require('fastify')({
logger: {
level: process.env.NODE_ENV === 'production' ? 'info' : 'debug',
redact: ['req.headers.authorization'],
serializers: {
req(req) {
return {
method: req.method,
url: req.url
}
}
}
}
})
2.3 使用Schema #
Schema验证和序列化可以显著提升性能:
javascript
fastify.get('/users/:id', {
schema: {
params: {
type: 'object',
properties: {
id: { type: 'integer' }
}
},
response: {
200: {
type: 'object',
properties: {
id: { type: 'integer' },
name: { type: 'string' }
}
}
}
}
}, handler)
三、路由优化 #
3.1 路由顺序 #
将高频路由放在前面:
javascript
fastify.get('/health', handler)
fastify.get('/api/v1/users', handler)
fastify.get('/api/v1/products', handler)
fastify.get('/api/v1/:resource/:id', handler)
3.2 路由约束 #
使用约束避免动态路由:
javascript
fastify.route({
method: 'GET',
url: '/api',
constraints: { host: 'api.example.com' },
handler
})
fastify.route({
method: 'GET',
url: '/api',
constraints: { host: 'admin.example.com' },
handler
})
3.3 避免通配符滥用 #
javascript
fastify.get('/files/:type/:name', handler)
fastify.get('/files/*', handler)
四、中间件优化 #
4.1 减少中间件数量 #
javascript
fastify.addHook('onRequest', async (request, reply) => {
request.startTime = Date.now()
request.id = generateRequestId()
})
4.2 条件性中间件 #
javascript
fastify.addHook('preHandler', async (request, reply) => {
if (request.routeConfig.auth) {
await authenticate(request, reply)
}
})
4.3 异步优化 #
javascript
fastify.addHook('onResponse', async (request, reply) => {
setImmediate(() => {
logToExternalService(request, reply)
})
})
五、缓存策略 #
5.1 响应缓存 #
javascript
fastify.get('/cached-data', async (request, reply) => {
reply
.header('Cache-Control', 'public, max-age=3600')
.header('ETag', generateETag(data))
return data
})
5.2 条件请求 #
javascript
fastify.get('/conditional', async (request, reply) => {
const etag = generateETag(data)
if (request.headers['if-none-match'] === etag) {
reply.code(304).send()
return
}
reply.header('ETag', etag)
return data
})
5.3 Redis缓存 #
javascript
fastify.register(require('@fastify/redis'), {
host: 'localhost',
port: 6379
})
fastify.get('/users/:id', async (request, reply) => {
const cacheKey = `user:${request.params.id}`
const cached = await fastify.redis.get(cacheKey)
if (cached) {
return JSON.parse(cached)
}
const user = await getUser(request.params.id)
await fastify.redis.set(cacheKey, JSON.stringify(user), 'EX', 3600)
return user
})
5.4 内存缓存 #
javascript
const cache = new Map()
fastify.get('/users/:id', async (request, reply) => {
const cacheKey = request.params.id
if (cache.has(cacheKey)) {
const { data, expiry } = cache.get(cacheKey)
if (Date.now() < expiry) {
return data
}
cache.delete(cacheKey)
}
const user = await getUser(request.params.id)
cache.set(cacheKey, {
data: user,
expiry: Date.now() + 3600000
})
return user
})
六、数据库优化 #
6.1 连接池 #
javascript
fastify.register(require('@fastify/mongodb'), {
url: 'mongodb://localhost:27017',
database: 'myapp',
maxPoolSize: 100,
minPoolSize: 10
})
6.2 查询优化 #
javascript
fastify.get('/users', async (request, reply) => {
const { page = 1, limit = 10 } = request.query
const users = await fastify.mongo.db
.collection('users')
.find({})
.project({ name: 1, email: 1 })
.skip((page - 1) * limit)
.limit(limit)
.toArray()
return users
})
6.3 批量操作 #
javascript
fastify.post('/users/batch', async (request, reply) => {
const users = request.body.users
const result = await fastify.mongo.db
.collection('users')
.insertMany(users)
return { inserted: result.insertedCount }
})
七、压缩优化 #
7.1 响应压缩 #
javascript
fastify.register(require('@fastify/compress'), {
global: true,
threshold: 1024,
encodings: ['gzip', 'deflate', 'br']
})
7.2 条件压缩 #
javascript
fastify.get('/large-data', {
compress: {
type: 'gzip',
threshold: 1024
}
}, async (request, reply) => {
return largeData
})
八、并发优化 #
8.1 集群模式 #
javascript
const cluster = require('cluster')
const os = require('os')
if (cluster.isPrimary) {
const cpus = os.cpus().length
for (let i = 0; i < cpus; i++) {
cluster.fork()
}
cluster.on('exit', (worker) => {
cluster.fork()
})
} else {
const fastify = require('fastify')()
fastify.listen({ port: 3000 })
}
8.2 PM2部署 #
ecosystem.config.js:
javascript
module.exports = {
apps: [{
name: 'fastify-app',
script: './app.js',
instances: 'max',
exec_mode: 'cluster',
autorestart: true,
watch: false,
max_memory_restart: '1G'
}]
}
九、内存优化 #
9.1 避免内存泄漏 #
javascript
fastify.addHook('onClose', async (instance) => {
await instance.db.close()
await instance.redis.quit()
})
9.2 监控内存 #
javascript
fastify.register(require('@fastify/under-pressure'), {
maxEventLoopDelay: 1000,
maxHeapUsedBytes: 100000000,
maxRssBytes: 100000000
})
fastify.get('/health', async (request, reply) => {
return {
memory: fastify.memoryUsage(),
eventLoopDelay: fastify.eventLoopDelay()
}
})
9.3 流式处理 #
javascript
fastify.get('/stream', async (request, reply) => {
const stream = fastify.mongo.db
.collection('users')
.find({})
.stream()
reply.type('application/json')
return stream
})
十、性能监控 #
10.1 请求监控 #
javascript
fastify.addHook('onRequest', async (request, reply) => {
request.metrics = {
start: process.hrtime.bigint()
}
})
fastify.addHook('onResponse', async (request, reply) => {
const duration = Number(process.hrtime.bigint() - request.metrics.start) / 1e6
fastify.log.info({
method: request.method,
url: request.url,
statusCode: reply.statusCode,
duration: `${duration.toFixed(2)}ms`
})
})
10.2 健康检查 #
javascript
fastify.get('/health', async (request, reply) => {
return {
status: 'ok',
timestamp: new Date().toISOString(),
uptime: process.uptime()
}
})
fastify.get('/ready', async (request, reply) => {
const checks = {
database: await checkDatabase(),
redis: await checkRedis()
}
const healthy = Object.values(checks).every(v => v)
reply.code(healthy ? 200 : 503)
return { checks, healthy }
})
10.3 性能分析 #
javascript
const profiler = require('v8-profiler-next')
fastify.get('/profile/start', async (request, reply) => {
profiler.startProfiling('CPU profile')
return { started: true }
})
fastify.get('/profile/stop', async (request, reply) => {
const profile = profiler.stopProfiling('CPU profile')
return profile
})
十一、最佳实践 #
11.1 生产配置 #
javascript
const fastify = require('fastify')({
logger: {
level: 'info',
redact: ['req.headers.authorization']
},
trustProxy: true,
ignoreTrailingSlash: true
})
11.2 优雅关闭 #
javascript
const signals = ['SIGINT', 'SIGTERM']
for (const signal of signals) {
process.on(signal, async () => {
console.log('Shutting down...')
await fastify.close()
process.exit(0)
})
}
11.3 错误处理 #
javascript
fastify.setErrorHandler((error, request, reply) => {
fastify.log.error(error)
reply.code(error.statusCode || 500).send({
error: process.env.NODE_ENV === 'production'
? 'Internal Server Error'
: error.message
})
})
十二、总结 #
本章我们学习了:
- 性能概述:性能优势、性能指标
- 基础优化:禁用功能、日志优化、Schema使用
- 路由优化:路由顺序、约束、避免通配符
- 中间件优化:减少数量、条件性、异步优化
- 缓存策略:响应缓存、条件请求、Redis缓存
- 数据库优化:连接池、查询优化、批量操作
- 压缩优化:响应压缩、条件压缩
- 并发优化:集群模式、PM2部署
- 内存优化:避免泄漏、监控内存、流式处理
- 性能监控:请求监控、健康检查、性能分析
接下来让我们学习实战案例!
最后更新:2026-03-28