nest熔断限流
【摘要】 nest熔断可以使用 circuit-breakerjs 这个包import { Injectable } from '@nestjs/common';import { CircuitBreaker } from 'circuit-breakerjs';@Injectable()export class CircuitBreakerService { private breaker: Ci...
nest熔断可以使用 circuit-breakerjs 这个包
import { Injectable } from '@nestjs/common';
import { CircuitBreaker } from 'circuit-breakerjs';
@Injectable()
export class CircuitBreakerService {
private breaker: CircuitBreaker;
constructor() {
this.breaker = new CircuitBreaker({
calibration: 5,
tolerance: 10,
bucketsNumber: 10,
slidingTimeWindow: 5000,
timeout: 2000,
onopen: () => {
console.log('opend');
},
onclose: () => {
console.log('close');
},
});
}
async execute<T>(fn: () => void) {
return this.breaker.run(fn);
}
}
- calibration: 校准值,表示在决定断路器状态时需要考虑的失败次数。当失败次数达到这个值时,断路器可能会进入开路状态。
- tolerance: 容忍度,表示在断路器进入开路状态之前可以容忍的失败率。例如,如果容忍度设置为50%,那么在当前窗口内失败率超过50%时,断路器可能会进入开路状态。
- bucketsNumber: 桶的数量,表示时间窗口内被划分为多少个桶。每个桶代表一个时间片段,用于统计失败次数。
- slidingTimeWindow: 滑动时间窗口,表示统计失败次数的时间范围,单位为毫秒。例如,设置为5000毫秒表示统计过去5秒内的失败次数。
- timeout: 超时时间,表示请求的超时时间,单位为毫秒。如果请求在这个时间内没有完成,将被视为失败。
- onopen: 断路器进入开路状态时的回调函数。当断路器进入开路状态时,这个函数会被调用。
- onclose: 断路器进入闭路状态时的回调函数。当断路器进入闭路状态时,这个函数会被调用。
import { Injectable, Inject } from '@nestjs/common';
import { CircuitBreakerService } from './circuitbreaker';
@Injectable()
export class AppService {
constructor(private readonly circuitBreakerService: CircuitBreakerService) {}
onModuleInit() {}
getHello(): string {
this.circuitBreakerService.execute(() => {});
return 'Hello World!';
}
}
限流器可以使用@nestjs/throttler
import { NestFactory } from '@nestjs/core';
import { ThrottlerGuard, ThrottlerModule } from '@nestjs/throttler';
import { AppModule } from './app.module';
async function bootstrap() {
const app = await NestFactory.create(AppModule);
// 配置全局节流器
app.useGlobalGuards(new ThrottlerGuard());
app.useGlobalPipes(new ThrottlerModule({
ttl: 60, // 每个IP在60秒内的请求限制
limit: 10, // 每个IP在60秒内最多允许10次请求
}).createThrottlerStorage());
await app.listen(3000);
}
bootstrap();
如果只想在特定的控制器或路由中使用节流器,可以在控制器或路由上使用 @UseGuards
装饰器:
import { Controller, Get, UseGuards } from '@nestjs/common';
import { ThrottlerGuard } from '@nestjs/throttler';
@Controller('api')
export class ApiController {
@Get('data')
@UseGuards(ThrottlerGuard)
getData() {
return { message: 'Data fetched successfully' };
}
}
使用redis可以自定义限流器
import { Injectable, NestMiddleware, HttpException, HttpStatus } from '@nestjs/common';
import { ThrottlerGuard } from '@nestjs/throttler';
import { createClient } from 'ioredis';
@Injectable()
export class CustomThrottlerGuard extends ThrottlerGuard {
private readonly redisClient = createClient({
host: 'localhost', // Redis 服务器地址
port: 6379, // Redis 服务器端口
});
constructor() {
super();
this.redisClient.connect();
}
async handleRequest(request: any, limit: number, ttl: number): Promise<void> {
const ip = request.ip;
const key = `throttle:${ip}`;
// 获取当前IP的请求计数
const current = await this.redisClient.get(key);
if (current) {
const count = parseInt(current, 10);
if (count >= limit) {
throw new HttpException('Too many requests', HttpStatus.TOO_MANY_REQUESTS);
}
// 增加请求计数
await this.redisClient.incr(key);
} else {
// 设置初始请求计数
await this.redisClient.set(key, 1, 'EX', ttl);
}
}
}
在 app.module.ts
文件中,注册自定义节流器:
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { AppController } from './app.controller';
import { AppService } from './app.service';
import { CustomThrottlerGuard } from './custom-throttler.guard';
@Module({
imports: [],
controllers: [AppController],
providers: [AppService, CustomThrottlerGuard],
})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(CustomThrottlerGuard)
.forRoutes('*'); // 应用到所有路由
}
}
在 app.controller.ts
文件中,使用自定义节流器
import { Controller, Get, UseGuards } from '@nestjs/common';
import { AppService } from './app.service';
import { CustomThrottlerGuard } from './custom-throttler.guard';
@Controller('api')
export class AppController {
constructor(private readonly appService: AppService) {}
@Get('data')
@UseGuards(CustomThrottlerGuard)
getData() {
return { message: 'Data fetched successfully' };
}
}
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱:
cloudbbs@huaweicloud.com
- 点赞
- 收藏
- 关注作者
评论(0)