Skip to Content
开发指南性能优化指南

性能优化指南

本指南介绍如何优化 MTPC 应用的性能,包括权限检查优化、缓存策略、数据库优化等。

性能优化概述

性能指标

指标目标值说明
权限检查延迟< 10ms单次权限检查的响应时间
策略评估延迟< 5ms策略评估的响应时间
缓存命中率> 90%缓存命中比例
数据库查询延迟< 50ms数据库查询的响应时间

性能优化层次

应用层优化 MTPC 层优化 数据库层优化 基础设施优化

权限检查优化

使用策略缓存

使用 @mtpc/policy-cache 扩展缓存权限检查结果。

import { createPolicyCachePlugin } from '@mtpc/policy-cache' const cachePlugin = createPolicyCachePlugin({ strategy: 'write-through', ttl: 300000, // 5 分钟 }) mtpc.use(cachePlugin)

批量权限检查

使用 checkMany() 一次性检查多个权限,减少数据库查询。

// 错误:多次检查 const canCreate = await mtpc.checkPermission(ctx, 'user', 'create') const canRead = await mtpc.checkPermission(ctx, 'user', 'read') const canUpdate = await mtpc.checkPermission(ctx, 'user', 'update') // 正确:批量检查 const results = await mtpc.checkMany(ctx, [ { resource: 'user', action: 'create' }, { resource: 'user', action: 'read' }, { resource: 'user', action: 'update' }, ])

预加载权限

在请求开始时预加载所有权限,避免重复检查。

import { createContext } from '@mtpc/core' // 预加载权限 const ctx = createContext({ tenant: { id: 'tenant-001' }, subject: { id: 'user-123', type: 'user' }, preloadPermissions: true, // 预加载所有权限 }) // 后续权限检查从内存中读取 const canCreate = ctx.hasPermission('user:create') const canRead = ctx.hasPermission('user:read')

缓存策略

缓存策略选择

策略描述适用场景
Write-Through写入时同步更新缓存读多写少
Write-Behind写入时异步更新缓存写多读少
Refresh-Ahead提前刷新缓存有过期时间要求

Write-Through 策略

const cachePlugin = createPolicyCachePlugin({ strategy: 'write-through', ttl: 300000, // 5 分钟 })

特点:

  • 写入时同步更新缓存
  • 缓存与数据源强一致
  • 适合读多写少的场景

Write-Behind 策略

const cachePlugin = createPolicyCachePlugin({ strategy: 'write-behind', ttl: 300000, writeInterval: 5000, // 5 秒批量写入 })

特点:

  • 写入时异步更新缓存
  • 提高写入性能
  • 适合写多读少的场景

Refresh-Ahead 策略

const cachePlugin = createPolicyCachePlugin({ strategy: 'refresh-ahead', ttl: 300000, refreshAheadRatio: 0.8, // 剩余 80% 时间时刷新 })

特点:

  • 提前刷新缓存
  • 避免缓存失效延迟
  • 适合有过期时间要求的场景

缓存 TTL 设置

根据权限变更频率设置合适的 TTL。

变更频率推荐的 TTL
极少(分钟级)600000 (10 分钟)
较少(小时级)300000 (5 分钟)
中等(天级)180000 (3 分钟)
频繁(分钟级)60000 (1 分钟)

缓存失效策略

在权限变更时及时使缓存失效。

// 角色变更后使缓存失效 await rbac.updateRole('tenant-001', 'role-001', { permissions: ['new:permission'], }) // 使相关用户的缓存失效 await cachePlugin.state.cache.invalidate('tenant-001', 'user-123') // 或者使整个租户的缓存失效 await cachePlugin.state.cache.invalidate('tenant-001')

数据库优化

索引优化

为常用查询字段添加索引。

import { pgTable, uuid, text, index } from 'drizzle-orm/pg-core' export const users = pgTable('users', { id: uuid('id').primaryKey().defaultRandom(), email: text('email').notNull(), tenantId: uuid('tenant_id').notNull(), }, (table) => ({ tenantIdIdx: index('tenant_id_idx').on(table.tenantId), emailIdx: index('email_idx').on(table.email), tenantEmailIdx: index('tenant_email_idx').on(table.tenantId, table.email), }))

查询优化

使用高效的 SQL 查询。

// 错误:N+1 查询 const users = await db.select().from(users) for (const user of users) { const roles = await db.select().from(roles).where(eq(roles.userId, user.id)) user.roles = roles } // 正确:使用 JOIN const users = await db.select({ user: users, roles: roles, }).from(users) .leftJoin(roles, eq(roles.userId, users.id))

连接池优化

配置数据库连接池。

import { drizzle } from 'drizzle-orm/postgres-js' import postgres from 'postgres' const connection = postgres(process.env.DATABASE_URL, { max: 20, // 最大连接数 idle_timeout: 20, // 空闲超时 connect_timeout: 10, // 连接超时 }) export const db = drizzle(connection)

分区表

对大表进行分区。

-- 按时间分区 CREATE TABLE audit_logs ( id UUID PRIMARY KEY, tenant_id UUID NOT NULL, action TEXT NOT NULL, created_at TIMESTAMP NOT NULL ) PARTITION BY RANGE (created_at); -- 创建分区 CREATE TABLE audit_logs_2024_01 PARTITION OF audit_logs FOR VALUES FROM ('2024-01-01') TO ('2024-02-01');

应用层优化

异步处理

使用异步处理提高并发性能。

// 错误:串行处理 for (const user of users) { await sendWelcomeEmail(user.email) } // 正确:并行处理 await Promise.all(users.map(user => sendWelcomeEmail(user.email)))

批量操作

使用批量操作减少数据库往返。

// 错误:逐个插入 for (const user of users) { await db.insert(users).values(user) } // 正确:批量插入 await db.insert(users).values(users)

请求合并

合并多个请求为一个请求。

// 错误:多个请求 const user = await fetchUser(userId) const permissions = await fetchPermissions(userId) const roles = await fetchRoles(userId) // 正确:合并请求 const data = await fetchUserData(userId) // { user, permissions, roles }

监控和调优

性能监控

启用 MTPC 的性能监控。

const mtpc = createMTPC({ performance: { enabled: true, threshold: 100, // 超过 100ms 记录警告 }, })

性能指标

获取性能统计信息。

const stats = mtpc.getPerformanceStats() console.log('Average permission check time:', stats.avgPermissionCheckTime) console.log('Cache hit rate:', stats.cacheHitRate) console.log('Total operations:', stats.totalOperations)

慢查询分析

分析慢查询并优化。

// 启用慢查询日志 const db = drizzle(connection, { logger: { logQuery: (query, params) => { const start = Date.now() return () => { const duration = Date.now() - start if (duration > 100) { console.warn('Slow query:', { query, params, duration }) } } }, }, })

性能分析工具

使用性能分析工具。

// 使用 Node.js 性能分析 const { performance } = require('perf_hooks') const start = performance.now() // 执行代码 await mtpc.checkPermission(ctx, 'user', 'create') const duration = performance.now() - start console.log('Duration:', duration)

性能优化示例

优化前

// 每次请求都检查权限 app.get('/api/users', async (c) => { const users = await db.select().from(users) const result = [] for (const user of users) { // 每个用户都检查权限 const canRead = await mtpc.checkPermission(ctx, 'user', 'read') if (canRead.allowed) { result.push(user) } } return c.json(result) })

优化后

// 预加载权限,批量检查 app.get('/api/users', async (c) => { // 预加载所有权限 const ctx = createContext({ tenant: c.get('tenant'), subject: c.get('subject'), preloadPermissions: true, }) const users = await db.select().from(users) // 从内存中读取权限 const result = users.filter(user => ctx.hasPermission('user:read')) return c.json(result) })

性能优化清单

应用层

  • 使用批量权限检查
  • 预加载权限
  • 使用异步处理
  • 使用批量操作
  • 合并请求

MTPC 层

  • 启用策略缓存
  • 设置合适的缓存 TTL
  • 及时使缓存失效
  • 启用性能监控
  • 分析性能指标

数据库层

  • 添加合适的索引
  • 优化 SQL 查询
  • 配置连接池
  • 对大表进行分区
  • 分析慢查询

基础设施层

  • 使用 CDN
  • 启用 HTTP 缓存
  • 使用负载均衡
  • 配置自动扩展
  • 监控资源使用

常见问题

Q: 如何提高缓存命中率?

A: 设置合适的缓存 TTL,及时使缓存失效,使用批量权限检查。

Q: 如何减少数据库查询?

A: 使用批量操作、JOIN 查询、缓存查询结果。

Q: 如何处理高并发?

A: 使用连接池、异步处理、负载均衡、自动扩展。

Q: 如何优化慢查询?

A: 添加索引、优化 SQL 查询、使用分区表、分析查询计划。


继续学习: 迁移指南

Last updated on