JWT 的性能优化对于高并发系统非常重要。以下是主要的优化策略和实现方法:
1. 签名算法优化
选择更快的算法
javascript// ES256 比 RS256 更快,签名更小 const jwt = require('jsonwebtoken'); // 使用 ES256 (ECDSA) const token = jwt.sign(payload, privateKey, { algorithm: 'ES256' // 比 RS256 快约 2-3 倍 }); // HS256 最快,但需要安全地管理密钥 const token = jwt.sign(payload, secretKey, { algorithm: 'HS256' // 最快,但密钥管理复杂 });
算法性能对比
| 算法 | 签名速度 | 验证速度 | 签名大小 | 推荐场景 |
|---|---|---|---|---|
| HS256 | ⭐⭐⭐⭐⭐ | ⭐⭐⭐⭐⭐ | ~32B | 单体应用 |
| RS256 | ⭐⭐ | ⭐⭐⭐ | ~256B | 分布式系统 |
| ES256 | ⭐⭐⭐ | ⭐⭐⭐⭐ | ~64B | 移动应用 |
2. 缓存优化
验证结果缓存
javascriptconst NodeCache = require('node-cache'); const tokenCache = new NodeCache({ stdTTL: 300, // 5分钟缓存 checkperiod: 60 }); function verifyTokenCached(token) { const cacheKey = `token:${token}`; // 检查缓存 const cached = tokenCache.get(cacheKey); if (cached) { return cached; } // 验证 token const decoded = jwt.verify(token, SECRET_KEY); // 缓存结果 tokenCache.set(cacheKey, decoded); return decoded; } // 使用示例 app.get('/api/data', (req, res) => { const token = req.headers['authorization']?.replace('Bearer ', ''); const decoded = verifyTokenCached(token); // 使用缓存 res.json({ data: '...' }); });
公钥缓存
javascriptconst jose = require('node-jose'); let cachedKeyStore = null; let cacheExpiry = 0; async function getKeyStore() { if (cachedKeyStore && Date.now() < cacheExpiry) { return cachedKeyStore; } // 从远程获取 JWK Set const response = await fetch('https://auth.example.com/.well-known/jwks.json'); const jwks = await response.json(); // 创建 keystore const keystore = await jose.JWK.createKeyStore(); for (const jwk of jwks.keys) { await keystore.add(jwk); } cachedKeyStore = keystore; cacheExpiry = Date.now() + (5 * 60 * 1000); // 5分钟 return keystore; }
3. Token 大小优化
减少 Payload 大小
javascript// ❌ 不好的做法:字段名过长 const token = jwt.sign({ userId: '1234567890', userName: 'john.doe@example.com', userRole: 'administrator', userPermissions: ['read', 'write', 'delete'] }, SECRET_KEY); // ✅ 好的做法:使用短字段名 const token = jwt.sign({ uid: '1234567890', // userId -> uid unm: 'john.doe@example.com', // userName -> unm rol: 'admin', // userRole -> rol prms: ['r', 'w', 'd'] // userPermissions -> prms }, SECRET_KEY); // ✅ 更好的做法:只存储 ID,其他信息从数据库获取 const token = jwt.sign({ uid: '1234567890' }, SECRET_KEY);
使用压缩
javascriptconst { deflate, inflate } = require('pako'); function compressPayload(payload) { const json = JSON.stringify(payload); const compressed = deflate(json); return compressed.toString('base64'); } function decompressPayload(compressed) { const buffer = Buffer.from(compressed, 'base64'); const decompressed = inflate(buffer); return JSON.parse(decompressed.toString()); } // 使用示例 const payload = { uid: '123', unm: 'john', rol: 'admin' }; const compressed = compressPayload(payload); const token = jwt.sign({ data: compressed }, SECRET_KEY);
4. 异步验证
使用异步 API
javascript// ❌ 同步验证(阻塞) app.get('/api/data', (req, res) => { const token = req.headers['authorization']?.replace('Bearer ', ''); const decoded = jwt.verify(token, SECRET_KEY); // 阻塞 res.json({ data: '...' }); }); // ✅ 异步验证(非阻塞) app.get('/api/data', async (req, res) => { const token = req.headers['authorization']?.replace('Bearer ', ''); try { const decoded = await verifyTokenAsync(token); res.json({ data: '...' }); } catch (error) { res.status(401).json({ error: 'Invalid token' }); } }); // 异步验证函数 function verifyTokenAsync(token) { return new Promise((resolve, reject) => { jwt.verify(token, SECRET_KEY, (err, decoded) => { if (err) { reject(err); } else { resolve(decoded); } }); }); }
5. 批量验证
批量验证多个 Token
javascriptfunction verifyTokensBatch(tokens) { return tokens.map(token => { try { const decoded = jwt.verify(token, SECRET_KEY); return { token, valid: true, decoded }; } catch (error) { return { token, valid: false, error: error.message }; } }); } // 使用示例 const tokens = ['token1', 'token2', 'token3']; const results = verifyTokensBatch(tokens); const validTokens = results.filter(r => r.valid);
6. 数据库优化
减少数据库查询
javascript// ❌ 每次请求都查询数据库 app.get('/api/user', async (req, res) => { const decoded = jwt.verify(token, SECRET_KEY); const user = await db.query('SELECT * FROM users WHERE id = ?', [decoded.userId]); res.json(user); }); // ✅ 使用 Redis 缓存用户信息 const redis = require('redis'); const client = redis.createClient(); app.get('/api/user', async (req, res) => { const decoded = jwt.verify(token, SECRET_KEY); // 先从缓存获取 let user = await client.get(`user:${decoded.userId}`); if (!user) { // 缓存未命中,查询数据库 user = await db.query('SELECT * FROM users WHERE id = ?', [decoded.userId]); // 存入缓存 await client.setex(`user:${decoded.userId}`, 300, JSON.stringify(user)); } else { user = JSON.parse(user); } res.json(user); });
7. 连接池优化
使用连接池
javascriptconst mysql = require('mysql2/promise'); // 创建连接池 const pool = mysql.createPool({ host: 'localhost', user: 'root', password: 'password', database: 'mydb', waitForConnections: true, connectionLimit: 10, // 连接池大小 queueLimit: 0 }); app.get('/api/data', async (req, res) => { const decoded = jwt.verify(token, SECRET_KEY); // 使用连接池 const [rows] = await pool.query('SELECT * FROM data WHERE user_id = ?', [decoded.userId]); res.json(rows); });
8. 负载均衡
多实例部署
javascript// 使用 Redis 共享缓存 const redis = require('redis'); const client = redis.createClient({ host: 'redis-server', port: 6379 }); // 所有实例共享同一个 Redis 缓存 function verifyTokenCached(token) { return new Promise(async (resolve, reject) => { const cacheKey = `token:${token}`; // 从 Redis 获取缓存 const cached = await client.get(cacheKey); if (cached) { return resolve(JSON.parse(cached)); } // 验证 token const decoded = jwt.verify(token, SECRET_KEY); // 存入 Redis await client.setex(cacheKey, 300, JSON.stringify(decoded)); resolve(decoded); }); }
9. 监控和调优
性能监控
javascriptconst promClient = require('prom-client'); // 创建指标 const tokenVerifyDuration = new promClient.Histogram({ name: 'token_verify_duration_seconds', help: 'Token verification duration in seconds', buckets: [0.001, 0.005, 0.01, 0.05, 0.1, 0.5, 1] }); const tokenCacheHits = new promClient.Counter({ name: 'token_cache_hits_total', help: 'Total number of token cache hits' }); const tokenCacheMisses = new prom.Client.Counter({ name: 'token_cache_misses_total', help: 'Total number of token cache misses' }); // 监控验证性能 function verifyTokenWithMetrics(token) { const end = tokenVerifyDuration.startTimer(); try { const decoded = verifyTokenCached(token); tokenCacheHits.inc(); return decoded; } catch (error) { tokenCacheMisses.inc(); throw error; } finally { end(); } } // 指标端点 app.get('/metrics', (req, res) => { res.set('Content-Type', promClient.register.contentType); res.end(promClient.register.metrics()); });
10. 最佳实践总结
性能优化清单
- 使用更快的签名算法(ES256)
- 实现验证结果缓存
- 减少 Payload 大小
- 使用异步验证
- 批量验证多个 Token
- 减少数据库查询
- 使用连接池
- 实现负载均衡
- 添加性能监控
- 定期分析和优化
性能基准测试
javascriptconst Benchmark = require('benchmark'); const suite = new Benchmark.Suite; suite .add('HS256', () => { jwt.sign(payload, secretKey, { algorithm: 'HS256' }); }) .add('RS256', () => { jwt.sign(payload, privateKey, { algorithm: 'RS256' }); }) .add('ES256', () => { jwt.sign(payload, privateKey, { algorithm: 'ES256' }); }) .on('cycle', (event) => { console.log(String(event.target)); }) .run();
通过以上优化策略,可以显著提升 JWT 认证系统的性能,支持更高的并发量。