可能导致性能瓶颈的原因
- 路由匹配算法复杂度高:过多的路由规则或复杂的正则表达式匹配,导致每次请求匹配路由时需要遍历大量规则,消耗过多CPU时间。
- 中间件过多或性能不佳:每个路由可能挂载了多个中间件,若中间件处理逻辑复杂或存在阻塞操作(如同步I/O),会拖慢请求处理速度。
- 数据库查询性能低:路由处理函数中频繁进行数据库查询,且数据库查询未优化,例如未使用索引、查询语句复杂等,导致数据库响应时间长,影响路由整体性能。
- 缓存缺失:对于一些不经常变化的数据,未进行缓存,每次请求都重新计算或查询,浪费资源。
性能优化思路及关键实现步骤
- 优化路由匹配
- 简化路由规则:避免使用过于复杂的正则表达式,尽量使用简洁的字符串匹配。
- 合理组织路由:将高频访问的路由放在前面,减少匹配次数。例如:
app.get('/home', homeHandler);
app.get('/about', aboutHandler);
// 而不是将低频的放前面
app.get('/terms-and-conditions', termsHandler);
- 优化中间件
- 去除不必要中间件:检查每个中间件的必要性,删除对当前路由无用的中间件。
- 优化中间件逻辑:将中间件中的阻塞操作改为异步操作。比如使用异步文件读取
fs.readFile
替代同步的fs.readFileSync
。
- 数据库查询优化
- 添加索引:分析数据库查询语句,对经常用于查询条件的字段添加索引。例如在MySQL中:
CREATE INDEX idx_username ON users (username);
- **批量查询**:尽量减少多次单个查询,将多个相关查询合并为一次批量查询。例如在MongoDB中,可以使用`$in`操作符来查询多个文档:
const userIds = [1, 2, 3];
User.find({ _id: { $in: userIds } }, (err, users) => {
// 处理查询结果
});
- 添加缓存
- 内存缓存:使用
node-cache
等库在内存中缓存数据。例如:
const NodeCache = require('node-cache');
const myCache = new NodeCache();
app.get('/data', (req, res) => {
const cachedData = myCache.get('myData');
if (cachedData) {
return res.json(cachedData);
}
// 从数据库或其他数据源获取数据
const newData = getNewData();
myCache.set('myData', newData);
res.json(newData);
});
- **分布式缓存**:对于大型应用,可以使用Redis作为分布式缓存,提高缓存的可用性和扩展性。
安全加固思路及关键实现步骤
- 防止SQL注入
- 使用参数化查询:在使用SQL数据库(如MySQL、PostgreSQL)时,使用参数化查询而非字符串拼接。例如在MySQL中:
const mysql = require('mysql');
const connection = mysql.createConnection({
host: 'localhost',
user: 'root',
password: 'password',
database: 'test'
});
const username = req.body.username;
const query = 'SELECT * FROM users WHERE username =?';
connection.query(query, [username], (err, results) => {
if (err) throw err;
res.json(results);
});
- 防止XSS攻击
- 输入验证和转义:对用户输入的数据进行严格验证,只允许合法字符。同时,对输出到页面的数据进行转义。例如使用
DOMPurify
库:
const DOMPurify = require('dompurify');
const input = req.body.input;
const cleanInput = DOMPurify.sanitize(input);
// 使用cleanInput进行后续操作
- **设置HTTP头**:设置`Content - Security - Policy`(CSP)头,限制页面可以加载的资源来源,防止恶意脚本注入。在Express中可以这样设置:
app.use((req, res, next) => {
res.setHeader('Content - Security - Policy', "default - src'self'");
next();
});
- 防止CSRF攻击
- 生成和验证CSRF令牌:使用
csurf
等库生成和验证CSRF令牌。例如:
const csrf = require('csurf');
const csrfProtection = csrf({ cookie: true });
app.get('/form', csrfProtection, (req, res) => {
res.render('form', { csrfToken: req.csrfToken() });
});
app.post('/submit', csrfProtection, (req, res) => {
// 处理表单提交
});