性能优化 #

一、性能概述 #

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
  })
})

十二、总结 #

本章我们学习了:

  1. 性能概述:性能优势、性能指标
  2. 基础优化:禁用功能、日志优化、Schema使用
  3. 路由优化:路由顺序、约束、避免通配符
  4. 中间件优化:减少数量、条件性、异步优化
  5. 缓存策略:响应缓存、条件请求、Redis缓存
  6. 数据库优化:连接池、查询优化、批量操作
  7. 压缩优化:响应压缩、条件压缩
  8. 并发优化:集群模式、PM2部署
  9. 内存优化:避免泄漏、监控内存、流式处理
  10. 性能监控:请求监控、健康检查、性能分析

接下来让我们学习实战案例!

最后更新:2026-03-28