Web 应用通常在服务端获取数据库中的数据,然后返回到前端渲染,在对时效性要求不高的数据中大量的请求、频繁的数据库读取会导致服务端压力过大。我们使用Express框架时可以对返回信息进行缓存,在指定时间内进行访问自动返回之前的数据。
Express最主要的插件基础都是使用中间件来完成,本次缓存插件也开发后使用中间件的形式进行使用。使用memory-cache或者lru-cache进行缓存保存。
中间件代码:
memory-cache
代码语言:javascript复制import type { NextFunction, Response, Request } from "express";
import mcache from "memory-cache";
const cache = (req: Request, res: any, next: NextFunction) => {
let key = req.originalUrl || req.url;//以接口路径作为key
let cachedBody = mcache.get(key);
// 检测key是否有对应的数据.如果有就直接返回
if (cachedBody) {
res.json(cachedBody);
return;
} else {
//复制一个 json函数一个用来取值一个用来返回值
//重写JSON方法,在路由函数调用JSON方法时获取到需要缓存的数据,然后通过复制的jsonResponse进行返回
res.jsonResponse = res.json;
res.json = (value: any) => {
res.jsonResponse(value);
mcache.put(key, value, 10000 * 1000);
};
next();
}
};
export default cache;
本项目也正在使用这个插件使用Express TypeScript编写的缓存中间件,缓存自定义10000秒时间有效。同时使用memory-cache插件进行缓存数据管理。
lru-cache
代码语言:javascript复制import type { NextFunction, Response, Request } from "express";
import LRUCache from "lru-cache";
const mcache = new LRUCache({
max: 200,
ttl: 1 * 60 * 60 * 1000, // 1小时缓存
});
/**
* 缓存中间件
*/
const cache = (req: Request, res: any, next: NextFunction) => {
let key = req.originalUrl || req.url;//以接口路径作为key
let cacheData = mcache.get(key);
// 检测key是否有对应的数据.如果有就直接返回
if (cacheData) {
res.json(cacheData);
return;
} else {
//复制一个 json函数一个用来取值一个用来返回值
//重写JSON方法,在路由函数调用JSON方法时获取到需要缓存的数据,然后通过复制的jsonResponse进行返回
res.jsonResponse = res.json;
res.json = (value: any) => {
res.jsonResponse(value);
mcache.get(key, value);
};
next();
}
};
export default cache;
export { mcache };
思路:
- 定义中间件并且使用路径作为对象的key
- 判断是否有缓存,如果有直接返回保存的对象
- 如果没有,复制一个res.json函数,之后重写res.json,使得之后的路由函数在调用res.json时我们可以获取到他的值
- 使用复制出来的res.json (res.jsonResponse) 返回数据,并且将返回的数据保存在memory-cache中
- 在需要缓存的路由中导入,并且挂在中间件的位置上
效果:
第一次(缓存数据):
第二次(读取缓存):
对于缓存插件的选择并不固定,我们可以选择使用周下载量更多的插件:lru-cachel来进行缓存,但是这个插件虽然支持的参数多但是如果只是简单的缓存接口数据使用这个是饭圈没有必要的,memory-cache和lru-cache的选择要看具体业务情况而定。