nest熔断限流

举报
yd_254179665 发表于 2025/07/03 14:48:40 2025/07/03
【摘要】 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

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。