整体策略
- 缓存策略:
- 对于静态资源,采用HTTP缓存机制。可以设置
Cache - Control
头,区分不同类型的静态资源设置不同的缓存时长。例如,对于长期不变的CSS、JS和图片等资源设置较长的缓存时间;对于经常变动的资源(如HTML页面)设置较短的缓存时间或者不缓存。
- 同时,可以在应用层实现本地缓存(如使用
node - cache
库),对于一些不经常变化且计算成本较高的数据进行缓存,减少重复计算。
- 压缩策略:
- 选择合适的压缩算法,如Gzip或Brotli。一般来说,Brotli在压缩率上优于Gzip,尤其是对于文本数据,但需要考虑浏览器兼容性。
- 对所有响应数据(包括动态生成的数据和静态资源)进行压缩,以减少传输的数据量,提高响应速度。
代码层面实现缓存与压缩协同工作
- 缓存实现:
- HTTP缓存:在Node.js应用中,使用Express框架举例,设置
Cache - Control
头:
const express = require('express');
const app = express();
// 对于静态资源设置较长缓存时间
app.use('/static', express.static('public', {
maxAge: 31536000 // 1年,单位毫秒
}));
// 对于动态响应,根据业务设置不同缓存策略
app.get('/data', (req, res) => {
// 设置较短缓存时间
res.set('Cache - Control','public, max - age = 60');
res.send('Dynamic data');
});
const NodeCache = require('node - cache');
const myCache = new NodeCache();
app.get('/expensive - data', (req, res) => {
const cachedData = myCache.get('expensive - data - key');
if (cachedData) {
res.send(cachedData);
} else {
// 计算昂贵数据
const expensiveData = calculateExpensiveData();
myCache.set('expensive - data - key', expensiveData);
res.send(expensiveData);
}
});
- 压缩实现:
const express = require('express');
const app = express();
const compression = require('compression');
app.use(compression());
app.get('/data', (req, res) => {
res.send('Some data to be compressed');
});
const express = require('express');
const app = express();
const brotli = require('iltorb');
const acceptEncoding = require('accept - encoding');
app.use((req, res, next) => {
const encodings = acceptEncoding(req);
if (encodings['br']) {
res.set('Content - Encoding', 'br');
res.attachment('filename.br');
const compressor = brotli.createCompressor();
res.writeHead(200, { 'Content - Type': 'application/json' });
compressor.pipe(res);
compressor.write(JSON.stringify({ data: 'example' }));
compressor.end();
} else {
// 回退到Gzip或不压缩
next();
}
});
app.use(compression());
app.get('/data', (req, res) => {
res.send('Some data to be compressed');
});
缓存更新处理
- HTTP缓存更新:
- 对于静态资源,通过修改文件名(如使用版本号或哈希值)来使浏览器重新请求资源,绕过缓存。例如,将
styles.css
改为styles.v1.css
。
- 对于动态数据,在数据发生变化时,通过设置较短的缓存时间或者直接不缓存,强制浏览器重新请求数据。
- 本地缓存更新:
- 在数据发生变化的业务逻辑处,手动更新缓存。例如,当某个数据库记录更新时,删除或更新本地缓存中对应的键值对:
// 假设数据库更新函数
function updateDatabaseRecord(record) {
// 执行数据库更新操作
// 更新缓存
myCache.del('related - data - key');
}
压缩格式选择
- 兼容性优先:优先检查浏览器是否支持Brotli压缩。可以通过
accept - encoding
库来解析请求头中的Accept - Encoding
字段,判断浏览器支持的压缩格式。如果浏览器支持Brotli,优先使用Brotli;否则,使用Gzip作为 fallback。
- 性能考量:在支持Brotli的情况下,Brotli通常能提供更好的压缩率,尤其是对于文本数据。但如果应用主要面向较旧的浏览器版本,Gzip可能是更合适的选择,因为它有更广泛的兼容性。同时,也需要考虑服务器的计算资源,Brotli压缩和解压缩通常比Gzip更消耗CPU资源,在高并发场景下需要权衡。