项目中,NestJS 的限流(Rate Limiting)不仅仅是简单的限速控制,而是强调:
以下是一个“标准”的 NestJS 限流方案:
@nestjs/throttler
配置基础限流(适用于单节点)pnpm add @nestjs/throttler
app.module.ts
import { ThrottlerModule } from '@nestjs/throttler';
@Module({
imports: [
ThrottlerModule.forRoot({
ttl: 60, // 每 60 秒窗口
limit: 10, // 允许 10 次请求
}),
],
})
export class AppModule {}
import { Throttle } from '@nestjs/throttler';
@Controller('auth')
export class AuthController {
@Throttle(5, 60) // 自定义:60秒内最多请求5次
@Post('login')
login(@Body() dto: LoginDto) {
// ...
}
}
单实例的 MemoryThrottlerStorage
无法满足分布式部署,推荐使用 Redis:
pnpm add cache-manager-ioredis ioredis
import { ThrottlerModule } from '@nestjs/throttler';
import { ThrottlerStorageRedisService } from 'nestjs-throttler-storage-redis';
@Module({
imports: [
ThrottlerModule.forRootAsync({
useFactory: () => ({
ttl: 60,
limit: 10,
storage: new ThrottlerStorageRedisService({
host: 'localhost',
port: 6379,
}),
}),
}),
],
})
export class AppModule {}
可封装配置为
.env
动态环境变量 +config.module
自定义根据用户ID、IP、接口路径来限流:
import { ThrottlerGuard, ThrottlerModuleOptions } from '@nestjs/throttler';
import { ExecutionContext, Injectable } from '@nestjs/common';
@Injectable()
export class CustomThrottlerGuard extends ThrottlerGuard {
protected getTracker(req: Request): string {
const user = (req as any).user;
return user?.id || req.ip; // 优先按用户ID限流,否则按IP
}
protected getRequestResponse(context: ExecutionContext) {
const ctx = context.switchToHttp();
return { req: ctx.getRequest(), res: ctx.getResponse() };
}
}
在 main.ts
或某个模块中启用:
app.useGlobalGuards(new CustomThrottlerGuard());
将限流被拒绝的事件记录到:
你可以在自定义 Guard 中拦截超限的请求并发送日志:
protected throwThrottlingException(context: ExecutionContext): void {
const req = context.switchToHttp().getRequest();
console.warn(`[RateLimit] Blocked: ${req.ip}, Path: ${req.url}`);
super.throwThrottlingException(context);
}
如某些 IP 或用户角色无需限流,可添加白名单判断:
if (['127.0.0.1', 'admin-user-id'].includes(req.ip || user?.id)) {
return false; // skip throttling
}
维度 | 建议 |
---|---|
限流存储 | 推荐 Redis 支持多实例 |
限流 Key 设计 | 支持 IP + 用户ID + 路由等多种维度 |
限流策略 | 精细化配置,接口粒度调整 |
异常处理 | 自定义响应体、日志告警 |
观测性 | 打通 Prometheus / Grafana / ELK 等链路 |