响应压缩与性能优化
响应压缩与性能优化
Koa2作为一款轻量级的Node.js框架,在处理HTTP请求时经常面临响应体过大的问题。通过响应压缩可以有效减少传输数据量,提升应用性能。gzip和deflate是两种常见的压缩算法,Koa2中可以通过中间件轻松实现。
压缩中间件的基本使用
koa-compress是Koa2中最常用的压缩中间件,它基于Node.js原生zlib模块实现。安装只需执行:
npm install koa-compress
基础配置示例:
const compress = require('koa-compress');
const Koa = require('koa');
const app = new Koa();
app.use(compress({
threshold: 2048, // 只压缩大于此字节数的响应
gzip: {
flush: require('zlib').constants.Z_SYNC_FLUSH
},
deflate: {
flush: require('zlib').constants.Z_SYNC_FLUSH
},
br: false // 禁用brotli压缩
}));
压缩阈值与内容类型
合理设置压缩阈值能避免对小资源进行不必要的压缩:
app.use(compress({
threshold: 1024, // 1KB
filter(contentType) {
// 只压缩特定类型的响应
return /text|javascript|json|font/i.test(contentType);
}
}));
Brotli压缩的高级配置
Brotli是比gzip更高效的压缩算法,但需要Node.js 11.7.0+:
app.use(compress({
br: {
params: {
[zlib.constants.BROTLI_PARAM_QUALITY]: 11 // 最高压缩级别
}
}
}));
性能优化实践
静态资源处理
结合koa-static实现静态资源压缩:
const static = require('koa-static');
app.use(compress());
app.use(static('public', {
setHeaders(res) {
res.setHeader('Cache-Control', 'public, max-age=31536000');
}
}));
API响应优化
JSON响应压缩示例:
router.get('/api/data', async (ctx) => {
const bigData = await fetchDataFromDB(); // 获取大量数据
ctx.body = bigData; // 自动压缩
});
流式响应处理
对大文件使用流式压缩:
const fs = require('fs');
const path = require('path');
router.get('/large-file', async (ctx) => {
ctx.type = 'text/plain';
ctx.body = fs.createReadStream(path.join(__dirname, 'large.txt'));
});
缓存策略与压缩
合理的缓存能减少重复压缩:
app.use(async (ctx, next) => {
ctx.set('Cache-Control', 'no-cache');
await next();
if (ctx.fresh) {
ctx.status = 304;
ctx.body = null;
}
});
压缩与HTTPS性能
在HTTPS环境下注意CPU开销:
const https = require('https');
const fs = require('fs');
const options = {
key: fs.readFileSync('server.key'),
cert: fs.readFileSync('server.crt'),
ciphers: 'ECDHE-RSA-AES128-GCM-SHA256' // 优化加密套件
};
https.createServer(options, app.callback()).listen(443);
监控与调优
使用性能监控调整压缩参数:
const { performance } = require('perf_hooks');
app.use(async (ctx, next) => {
const start = performance.now();
await next();
const duration = performance.now() - start;
ctx.set('X-Response-Time', `${duration.toFixed(2)}ms`);
});
多层级压缩策略
针对不同路由采用不同压缩策略:
const apiRouter = new Router();
apiRouter.use(compress({ threshold: 512 }));
const staticRouter = new Router();
staticRouter.use(compress({ threshold: 2048 }));
app.use(apiRouter.routes());
app.use(staticRouter.routes());
客户端协商机制
正确处理客户端支持的压缩格式:
app.use(async (ctx, next) => {
await next();
const acceptEncoding = ctx.headers['accept-encoding'] || '';
ctx.vary('Accept-Encoding'); // 告知Vary头
});
内存管理
大响应时的内存控制:
app.use(compress({
flush: zlib.constants.Z_PARTIAL_FLUSH, // 部分刷新减少内存使用
chunkSize: 16 * 1024 // 16KB的块大小
}));
错误处理
压缩过程中的错误处理:
app.on('error', (err, ctx) => {
if (err.code === 'Z_DATA_ERROR') {
console.error('压缩数据错误:', err);
ctx.status = 500;
ctx.body = '压缩处理失败';
}
});
测试与基准
使用autocannon进行压力测试:
const autocannon = require('autocannon');
autocannon({
url: 'http://localhost:3000',
connections: 100,
duration: 10
}, console.log);
实际案例:电商API优化
商品列表API优化前后对比:
// 优化前
router.get('/products', async (ctx) => {
const products = await Product.find().lean();
ctx.body = products;
});
// 优化后
router.get('/products', async (ctx) => {
const products = await Product.find()
.select('name price image') // 只取必要字段
.lean()
.cache('1 hour'); // 添加缓存
ctx.body = products;
});
本站部分内容来自互联网,一切版权均归源网站或源作者所有。
如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn