一篇文章学会如何在 NestJS 中使用 Redis 并基于 Redis 实现接口访问限频率
前言
在处理高频数据操作和大规模并发请求的场合,我们需要一种机制能够快速读取和缓存数据,这时 Redis 就闪亮登场了。Redis 是一个开源的内存中数据结构存储系统,它可以用作数据库、缓存和消息中间件。
NestJS 是一个灵活且模块化的Node.js框架,它借鉴了Angular的设计哲学,提出了控制器、提供者和模块的概念,这为我们集成和使用Redis提供了便利。本文介绍如何在NestJS框架中集成Redis,并通过实际案例来展示使用Redis的优势。
集成步骤
一、 安装必要的包
在开始之前,我们需要在NestJS项目中安装 Redis 和 NestJS 对应的 Redis 模块。
npm install redis ioredis @nestjs-modules/ioredis @nestjs/common
这里我们使用 ioredis
,因为它是一个健壮的、功能全面的 Redis 客户端,与 nest-modules
相关联。
二、创建 Redis 模块
接下来,我们需要在 NestJS 应用中创建一个 Redis 模块。
// redis.module.ts
import { Module } from '@nestjs/common';
import { RedisModule } from '@nestjs-modules/ioredis';
@Module({
imports: [
RedisModule.forRoot({
config: {
host: 'localhost', // Redis 服务器地址
port: 6379, // Redis 端口
password: 'your_password', // 如果有设置密码的话
db: 0, // 如果你需要使用特定的数据库的话
},
}),
],
})
export class RedisCacheModule {}
在这个模块中,我们导入并配置了 Redis。我们需要确保这些配置与你的 Redis 服务器设置匹配。
三、在服务中使用 Redis
配置好模块后,我们可以在服务中注入 Redis 客户端,并开始实现业务逻辑。
// app.service.ts
import { Injectable } from '@nestjs/common';
import { InjectRedis, Redis } from '@nestjs-modules/ioredis';
@Injectable()
export class AppService {
constructor(@InjectRedis() private readonly redis: Redis) {}
async getHello(): Promise<string> {
// 使用 Redis 设置值
await this.redis.set('hello', 'Hello from Redis!');
// 使用 Redis 获取值
return this.redis.get('hello');
}
// ... 其他业务逻辑 ...
}
在这个服务中,我们注入了 Redis 客户端,并在 getHello
方法中演示了如何设置和获取缓存。
四、控制器 Controller 调用服务
最后,让我们来创建一个控制器调用这个服务。
// app.controller.ts
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) {}
@Get()
getHello(): Promise<string> {
return this.appService.getHello();
}
}
控制器非常简单,它使用 @Get()
装饰器来处理根路由的 GET 请求,并调用 appService
中的 getHello
方法。
功能实现
通过将Redis集成到NestJS中,我们可以实现以下需求:
- 数据缓存:存储经常查询的数据提高处理速度。
- 会话管理:用Redis存储session信息,实现无状态的负载均衡。
- 排行榜系统:Redis的Sorted Set非常适合做排名操作。
- 发布/订阅:利用 Redis 实现分工系统,用于消息的异步处理。
- 限流:通过Redis的INCR和EXPIRE命令来实现API的限流。
- 作业队列:使用 Redis 的列表结构实现一个简单的作业队列。
实战:接口访问限制频率
为了控制访问速率并避免应用被过多的请求淹没,我们可以利用 Redis 来为我们的 API 接口实现限流功能。下面是一个简化的例子:
步骤一:实现限流拦截器
// api-rate-limiter.interceptor.ts
import {
Injectable,
NestInterceptor,
ExecutionContext,
CallHandler,
HttpException,
HttpStatus,
} from '@nestjs/common';
import { Observable } from 'rxjs';
import { InjectRedis, Redis } from '@nestjs-modules/ioredis';
import { tap } from 'rxjs/operators';
@Injectable()
export class ApiRateLimiterInterceptor implements NestInterceptor {
constructor(@InjectRedis() private readonly redis: Redis) {}
async intercept(context: ExecutionContext, next: CallHandler): Promise<Observable<any>> {
const key = 'rate-limit:' + context.switchToHttp().getRequest().ip;
const currentRequestCount = await this.redis.incr(key);
if (currentRequestCount === 1) {
// 设置 key 的超时时间
await this.redis.expire(key, 60); // 限流周期为 60 秒
}
if (currentRequestCount > 10) {
throw new HttpException('Too many requests', HttpStatus.TOO_MANY_REQUESTS);
}
return next.handle().pipe(
tap(() => {
// 在响应完成后,你可以在这里执行一些操作。
}),
);
}
}
要实现的这个拦截器会检查每个 IP 地址每分钟发出的请求,并且如果请求超过10次,将会抛出 429 Too Many Requests
错误。
步骤二:项目中使用限流拦截器
将这个拦截器中间件引入到你的应用中,可以在对应的控制器或全局应用中注册。
// 在主模块中全局注册
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { ApiRateLimiterInterceptor } from './api-rate-limiter.interceptor';
@Module({
// ...
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(ApiRateLimiterInterceptor)
.forRoutes('*'); // 应用到所有的路由
}
}
或者在特定的控制器上使用:
// app.controller.ts
import { Controller, UseInterceptors, Get } from '@nestjs/common';
import { ApiRateLimiterInterceptor } from './api-rate-limiter.interceptor';
@Controller()
@UseInterceptors(ApiRateLimiterInterceptor)
export class AppController {
// ...
}
总结
通过在 NestJS 中集成 Redis,我们不仅可以实现上述功能,还能设计更复杂的系统,如分布式系统通信、实时数据分析等等。Redis 的快速、灵活性加上 NestJS 的架构,能够让你的 Web 应用性能达到一个新的层次。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!