一篇文章学会如何在 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中,我们可以实现以下需求:

  1. 数据缓存:存储经常查询的数据提高处理速度。
  2. 会话管理:用Redis存储session信息,实现无状态的负载均衡。
  3. 排行榜系统:Redis的Sorted Set非常适合做排名操作。
  4. 发布/订阅:利用 Redis 实现分工系统,用于消息的异步处理。
  5. 限流:通过Redis的INCR和EXPIRE命令来实现API的限流。
  6. 作业队列:使用 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 应用性能达到一个新的层次。

  • 16
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
在Django1.8通过Redis实现接口访问频率制,可以使用django-redis库,并结合Django的间件实现。 首先,安装django-redis库: ``` pip install django-redis ``` 接着,在settings.py添加Redis配置: ```python CACHES = { "default": { "BACKEND": "django_redis.cache.RedisCache", "LOCATION": "redis://127.0.0.1:6379/1", "OPTIONS": { "CLIENT_CLASS": "django_redis.client.DefaultClient", } } } ``` 然后,创建一个middleware,用于对访问频率进行制: ```python from django.core.cache import cache from django.http import HttpResponseForbidden class RateLimitMiddleware(object): def __init__(self, get_response): self.get_response = get_response def __call__(self, request): # 获取IP地址 ip_address = request.META.get('REMOTE_ADDR') # 每分钟最多请求次数 per_minute = 100 # 每天最多请求次数 per_day = 1000 # 获取当前时间 now = datetime.datetime.now() # 生成每分钟和每天的缓存键值 minute_key = 'minute_%s_%s' % (ip_address, now.strftime('%Y%m%d%H%M')) day_key = 'day_%s_%s' % (ip_address, now.strftime('%Y%m%d')) # 获取每分钟和每天已经请求的次数 minute_count = cache.get(minute_key) or 0 day_count = cache.get(day_key) or 0 # 如果请求次数超过制,返回403错误 if minute_count >= per_minute: return HttpResponseForbidden('每分钟最多请求%d次' % per_minute) if day_count >= per_day: return HttpResponseForbidden('每天最多请求%d次' % per_day) # 将每分钟和每天的请求次数加1,并设置缓存过期时间 cache.set(minute_key, minute_count + 1, 60) cache.set(day_key, day_count + 1, 60 * 60 * 24) return self.get_response(request) ``` 最后,在settings.py添加middleware: ```python MIDDLEWARE = [ # ... 'path.to.RateLimitMiddleware', ] ``` 这样,每个IP地址每分钟和每天的请求次数就会被制在一定范围内了。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

乐闻x

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值