高速缓存
高速缓存
缓存是一种非常简单的技术
,有助于提高应用程序的性能。它充当临时数据存储,访问非常高效。
安装
我们首先需要安装所需的包:
$ npm install --save cache-manager
内存缓存
Nest为各种缓存存储提供统一的API。内置的是内存中的数据存储。但是,您可以轻松切换到更全面的解决方案,例如Redis。为了启用缓存,首先导入CacheModule
并调用其register()
方法。
import { CacheModule, Module } from '@nestjs/common';
import { AppController } from './app.controller';
@Module{
imports: [CacheModule.register()],
controllers: [AppController],
})
export class ApplicationModule {}
然后只是绑在CacheInterceptor
某处。
@Controller()
@UseInterceptors(CacheInterceptor)
export class AppController {
@Get()
findAll(): string[] {
return [];
}
}
警告
仅GET
缓存端点。
全局缓存
要减少所需样板量,可以一次绑定CacheInterceptor
到每个现有端点。
import { CacheModule, Module, CacheInterceptor } from '@nestjs/common';
import { AppController } from './app.controller';
import { APP_INTERCEPTOR } from '@nestjs/core';
@Module{
imports: [CacheModule.register()],
controllers: [AppController],
providers: [
{
provide: APP_INTERCEPTOR,
useClass: CacheInterceptor,
},
],
})
export class ApplicationModule {}
WebSockets和微服务
显然,您可以毫不费力地应用于CacheInterceptor
WebSocket订阅者以及Microservice的模式(无论使用何种传输方法)。
@CacheKey('events')
@UseInterceptors(CacheInterceptor)
@SubscribeMessage('events')
onEvent(client, data): Observable<string[]> {
return [];
}
提示
该@CacheKey()
装饰器从进口@nestjs/common
包。
但是,@CacheKey()
需要附加装饰器以指定用于随后存储和检索缓存数据的密钥。此外,请注意,您不应该缓存所有内容
。责任是执行某些业务操作而不是简单地查询数据的操作永远不应该被缓存。
自定义缓存
所有缓存数据都有自己的到期时间(TTL)。要自定义默认值,请将选项对象传递给register()
方法。
CacheModule.register{
ttl: 5, // seconds
max: 10, // maximum number of items in cache
})
不同的商店
我们充分利用了缓存管理器。该软件包支持各种有用的商店,例如Redis商店(此处列出完整列表)。要设置Redis存储,只需将包与correspoding选项一起传递给register()
方法即可。
import * as redisStore from 'cache-manager-redis-store';
import { CacheModule, Module } from '@nestjs/common';
import { AppController } from './app.controller';
@Module{
imports: [CacheModule.register{
store: redisStore,
host: 'localhost',
port: 6379,
})],
controllers: [AppController],
})
export class ApplicationModule {}
调整跟踪
默认情况下,Nest使用通过@CacheKey()
装饰器设置的请求URL(在HTTP应用程序中)或缓存键(在websockets和微服务中)将缓存记录与您的端点相关联。然而,有时您可能希望根据不同因素设置跟踪,例如,使用HTTP标头(例如Authorization
,正确识别profile
端点)。
为了实现这一点,创建一个子类CacheInterceptor
和覆盖trackBy()
方法。
@Injectable()
class HttpCacheInterceptor extends CacheInterceptor {
trackBy(context: ExecutionContext): string | undefined {
return 'key';
}
}
异步配置
通常,您可能希望异步传递模块选项,而不是事先传递它们。在这种情况下,使用registerAsync()
方法,提供了几种处理异步数据的方法。
第一种可能的方法是使用工厂功能:
CacheModule.forRootAsync{
useFactory: () => {
ttl: 5,
}),
})
显然,我们的工厂表现得像其他每一个(可能async
并且能够通过注入依赖关系inject
)。
CacheModule.forRootAsync{
imports: [ConfigModule],
useFactory: async (configService: ConfigService) => {
ttl: configService.getString('CACHE_TTL'),
}),
inject: [ConfigService],
})
或者,您可以使用类而不是工厂。
CacheModule.forRootAsync{
useClass: CacheConfigService,
})
上面的构造将CacheConfigService
在内部实例化CacheModule
,并将利用它来创建选项对象。在CacheConfigService
必须实现CacheOptionsFactory
的接口。
@Injectable()
class CacheConfigService implements CacheOptionsFactory {
createCacheOptions(): CacheModuleOptions {
return {
ttl: 5,
};
}
}
为了防止CacheConfigService
内部创建CacheModule
并使用从不同模块导入的提供程序,您可以使用useExisting
语法。
CacheModule.forRootAsync{
imports: [ConfigModule],
useExisting: ConfigService,
})
它的作用useClass
与一个关键区别相同 - CacheModule
将查找导入的模块以重新使用已创建的ConfigService
,而不是单独实例化它。