缓存模式
缓存模式可在全局或请求级等不同粒度下设置。全局设置时,所有由相同 alova 实例创建的 method 实例都会继承该设置。
是否使用缓存模式,以及使用哪种缓存模式需要根据场景而定,下面在单独介绍不同缓存模式时将会提及它们的使用场景。
内存模式(默认)
内存模式属于单级缓存(L1 缓存)模式,默认将缓存放在内存中,是最常用的缓存模式。
在默认情况下,GET 请求有 300000ms(5 分钟)的内存缓存时间,开发者也可以自定义设置缓存,请继续往下看。
客户端
在客户端中,刷新页面缓存即失效,内存模式一般用于解决短时间内(几分钟或几秒钟)频繁请求相同数据带来的性能消耗,例如当你在写 todo 详情页的时候,你可能会想到用户会频繁在 todo 列表中点击查看详情,如果用户重复查看某条详情时不再重复请求接口,并且能立即返回数据,提升了响应速度的同时也减小了服务器压力。此时我们就可以为某个 todo 详情 method 实例设置响应数据缓存。
alovaInstance.GET('/todo/list', {
// ...
cacheFor: {
// 设置缓存模式为内存模式
mode: 'memory',
// 单位为毫秒
// 当设置为`Infinity`,表示数据永不过期,设置为0或负数时表示不缓存
expire: 60 * 10 * 1000
}
});
内存模式为默认模式,你可以这样简写
alovaInstance.GET('/todo/list', {
// ...
cacheFor: 60 * 10 * 1000
});
服务端
在服务中通常在接口需要高访问频率和低延迟场景中使用,减轻下游服务器压力,使用方法与客户端相同。
在服务端中使用时需要注意:
- 过多的缓存会一直消耗服务器内存,你可以改用lru-cache控制内存消耗。
- 如果需要在单机的 nodejs 集群环境中共享缓存,可以使用@alova/psc创建进程间共享内存的缓存方案。
const { createPSCAdapter, NodeSyncAdapter } = require('@alova/psc');
const { LRUCache } = require('lru-cache');
function lRUCache(options = {}) {
const cache = new LRUCache(options);
return {
set(key, value) {
return cache.set(key, value);
},
get(key) {
return cache.get(key);
},
remove(key) {
return cache.delete(key);
},
clear() {
return cache.clear();
}
};
}
const alovaInstance = createAlova({
baseURL: 'https://api.alovajs.dev',
// 进程间共享缓存适配器
l1Cache: createPSCAdapter(
NodeSyncAdapter(),
lRUCache({
max: 1000,
ttl: 1000 * 60 * 10
})
)
});
内存缓存模式对应 l1 cache,在此我们更换了缓存适配器为进程间共享的 lru-cache,你也可以自定义存储适配器,例如当你只需要单级缓存时,你也可以直接将 l1 cache 设置为 redis 适配器。
恢复模式
恢复模式对应多级缓存,分别为 L1 和 L2 缓存。开启恢复模式后,响应数据会同时存储在 L1 和 L2 缓存中,当 L1 缓存失效时,会从 L2 缓存中读取数据,然后更新 L1 缓存,当 L2 缓存也失效时才会再次请求接口。
客户端
在客户端中,当还未过期的缓存即使刷新页面缓存也不会失效,它一般用于一些需要服务端管理,但基本不变的数据,如每年的节假日具体日期有所不同,但不会再变动,这种场景下我们只需设置缓存过期时间为今年的最后一刻即 可。
客户端中使用 alova 时默认使用localStorage作为 L2 存储适配器,你也可以自定义存储适配器。
在 method 实例上设置:
const todoListGetter = alovaInstance.Get('/todo/list', {
// ...
cacheFor: {
// 设置缓存模式为持久化模式
mode: 'restore',
// 缓存时间
expire: 60 * 10 * 1000
}
});
数据有变怎么办?
当设置了恢复模式的 method 实例,可能由于接口数据变动,或前端处理响应数据的逻辑变动,此时需要在发布应用后让用户重新缓存变动后的数据,此时你可以通过tag属性设置缓存标签,每一份持久化数据都包含一个tag标识,当tag改变后原有的持久化数据将会失效,并重新获取新的数据,并用新的tag进行标识。
const todoListGetter = alovaInstance.Get('/todo/list', {
// ...
cacheFor: {
mode: 'restore',
expire: 60 * 10 * 1000,
// 新增或修改tag参数,已缓存的数据将失效
// 建议使用版本号的形式管理
tag: 'v1'
}
});
服务端
一般用于多级缓存,使用 L1 作为内存缓存,L2 作为持久化缓存,例如 redis、memcached。
部分应用场景如下:
- 高访问频率和低延迟需求:例如热门新闻、商品详情,可以进一步减少网络开销,在网络不稳定时也保持更快的响应。
- 减轻下游服务器压力,例如有访问高峰期的服务,上层缓存可以有效减少对后端数据库和微服务的压力。
- 整合多个下游服务器的数据合并和处理,多个串行请求可能导致更长的响应时间,也可能因复杂的数据转换消耗性能,可将转换后的数据进行缓存。
- API 速率限制和计费,天气预报服务 API 每小时更新一次天气信息,地理位置数据 API 等。
在服务端使用 alova 时默认没有 L2 存储适配器,在服务端 L2 存储实践中分别提供了文件存储适配器和 redis 适配器的实现。你也可以自定义存储适配器,例如将 MongoDB、mysql 等数据库作为响应数据的存储适配器。
当 request body 是FormData、Blob