高速缓存

高速缓存

缓存是一种非常简单的技术,有助于提高应用程序的性能。它充当临时数据存储,访问非常高效。

安装

我们首先需要安装所需的包:

$ 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和微服务

显然,您可以毫不费力地应用于CacheInterceptorWebSocket订阅者以及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,而不是单独实例化它。