前言
在日常开发中,需要处理一些高并发的请求或者处理用户邮件认证等一些场景。那么就需要Redis了。
Redis 是一个开源的内存中数据结构存储系统,它可以用作数据库、缓存和消息中间件。
安装包
按照需要的包
pnpm install ioredis @nestjs-modules/ioredis @nestjs/common
这里我们使用 **ioredis
**,因为它是一个健壮的、功能全面的 Redis 客户端,与 **nest-modules
**相关联。
编写Redis服务模块
新建一个文件夹Redis,然后里面新建redis.module.ts文件,写入如下内容。
import { Module } from '@nestjs/common';
import { RedisModule } from '@nestjs-modules/ioredis';
@Module({
imports: [
RedisModule.forRoot({
type: 'single',
url: '127.0.0.1',
options: {
port: 6379,
password: 'password'
}
})
]
})
export class RedisCacheModule {}
之后在app.module.ts中导入
import { RedisCacheModule } from './redis/redis.module';
Module({
imports:[
RedisCacheModule
]
})
export class AppModule {}
使用案例
在需要使用到地方,例如我需要在users.service.ts中的接口使用
import { Injectable } from '@nestjs/common';
import { InjectRedis } from '@nestjs-modules/ioredis';
import Redis from 'ioredis';
@Injectable()
export class UsersService {
constructor(
@InjectRedis() private readonly redis: Redis
) {
async setUserPeerId(): Promise<string> {
// 使用 Redis 设置值
await this.redis.set('hello', 'Hello from Redis!');
// 使用 Redis 获取值
return this.redis.get('hello');
}
}
}
然后在对应的controller层调用函数。
扩展:接口访问限制频率
为了防止有人故意刷接口,或者对过多的请求搞奔溃应用,这里使用Redis做接口的限制
定义限流拦截器
// 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(() => {
// 在响应完成后,你可以在这里执行一些操作。
}),
);
}
}
项目中使用限流拦截器
将这个拦截器中间件引入到你的应用中,可以在对应的控制器或全局应用中注册。
-
全局拦截
import { ApiRateLimiterInterceptor } from './redis/api-rate-limiter.interceptor'; import { APP_INTERCEPTOR } from '@nestjs/core'; Module({ providers: [ { provide: APP_INTERCEPTOR, useClass: ApiRateLimiterInterceptor } ] }) export class AppModule {} // - 拦截器(Interceptor):用于在方法执行之前或之后添加额外逻辑,它们可以操作由函数返回的结果或异常。 // - 中间件(Middleware):通常用于执行请求前的一些操作,比如日志、请求解析等,是直接实现use方法的类。 // 一些博客中将拦截器用中间件来引入。这是不合适的
-
局部拦截
// user.controller.ts import { Controller, UseInterceptors } from '@nestjs/common'; import { ApiRateLimiterInterceptor } from './api-rate-limiter.interceptor'; @Controller('user') @UseInterceptors(ApiRateLimiterInterceptor) // 应用到UserController中的所有路由 export class UserController { // ... } // 或者 @Controller('user') export class UserController { @UseInterceptors(ApiRateLimiterInterceptor) // 仅应用到特定的路由处理程序 @Get('some-path') async someMethod() { // ... } // ... }
我这里为了统一方便就引入在全局上
评论区