Taocarts接口限流实操:基于Redis实现API防刷与流量管控

跨境Taocarts站点面向全球公网用户,极易遭遇恶意刷接口、爬虫高频请求、CC攻击等问题,高频无效请求会耗尽服务器带宽、数据库资源,导致正常用户接口卡顿、超时。原生系统无任何限流机制,接口完全裸奔,安全性极差。普通的内存限流仅支持单机部署,无法适配Taocarts集群多节点架构,存在限流失效漏洞。本文将基于Redis实现分布式接口限流,支持IP、用户账号双维度限流,支持自定义限流频次,适配集群部署,附带完整可落地代码。

分布式限流核心原理是借助Redis的过期键+自增计数器特性,实现全节点流量统一统计,区别于单机内存限流,集群环境下数据完全互通,不会出现限流阈值失效问题。我们将实现注解式限流,支持接口灵活配置秒级、分钟级访问频次,适配登录、下单、爬虫、查询等不同接口的防护需求。

首先封装Redis限流工具类,实现请求计数、过期设置、频次判断核心逻辑:

typescript 复制代码
// src/common/utils/redis-limit.util.ts
import { InjectRedis } from '@nestjs/redis';
import { Redis } from 'ioredis';
import { Injectable } from '@nestjs/common';

@Injectable()
export class RedisLimitUtil {
  constructor(@InjectRedis() private redis: Redis) {}

  /**
   * 分布式限流
   * @param key 限流唯一key
   * @param limit 最大请求次数
   * @param second 过期时间(秒)
   * @returns true=限流通过 false=触发限流
   */
  async limit(key: string, limit: number, second: number): Promise<boolean> {
    // 原子自增
    const count = await this.redis.incr(key);
    // 首次请求设置过期时间
    if (count === 1) {
      await this.redis.expire(key, second);
    }
    // 判断是否超过限制频次
    return count <= limit;
  }
}

自定义限流注解,实现接口灵活配置,无需重复编写限流逻辑:

typescript 复制代码
// src/common/decorator/rate-limit.decorator.ts
import { SetMetadata } from '@nestjs/common';

export interface RateLimitOption {
  limit: number;    // 限制次数
  second: number;   // 限制时间
  type: 'ip' | 'user'; // 限流维度
}

export const RateLimit = (options: RateLimitOption) => SetMetadata('rateLimit', options);

编写限流守卫,拦截所有带注解的接口,自动校验请求频次,IP限流适配匿名访问接口,用户限流适配登录后接口:

typescript 复制代码
// src/common/guard/rate-limit.guard.ts
import { CanActivate, ExecutionContext, Injectable } from '@nestjs/common';
import { Reflector } from '@nestjs/core';
import { RateLimitOption } from '../decorator/rate-limit.decorator';
import { RedisLimitUtil } from '../utils/redis-limit.util';
import { BusinessException, ErrorCode } from '../exception/business.exception';

@Injectable()
export class RateLimitGuard implements CanActivate {
  constructor(private reflector: Reflector, private redisLimit: RedisLimitUtil) {}

  async canActivate(context: ExecutionContext): Promise<boolean> {
    const options = this.reflector.get<RateLimitOption>('rateLimit', context.getHandler());
    if (!options) return true;

    const req = context.switchToHttp().getRequest();
    // 生成唯一限流KEY
    let key = `rate_limit:${context.getClass().name}:${context.getHandler().name}`;
    if (options.type === 'ip') {
      key += `:ip:${req.ip}`;
    } else {
      key += `:user:${req.user?.userId}`;
    }

    // 校验限流
    const pass = await this.redisLimit.limit(key, options.limit, options.second);
    if (!pass) {
      throw new BusinessException(ErrorCode.COMMON_ERROR, '请求过于频繁,请稍后再试');
    }
    return true;
  }
}

接口使用示例,给商品爬虫、登录、查询接口添加限流防护:

typescript 复制代码
@Controller('goods')
export class GoodsController {
  // IP限流:10秒最多访问5次,防爬虫刷取商品接口
  @Get('list')
  @UseGuards(RateLimitGuard)
  @RateLimit({ limit: 5, second: 10, type: 'ip' })
  async getGoodsList() {
    return await this.goodsService.getList();
  }

  // 用户限流:1分钟最多下单3次,防恶意刷单
  @Post('order/create')
  @UseGuards(RateLimitGuard)
  @RateLimit({ limit: 3, second: 60, type: 'user' })
  async createOrder() {
    // 下单逻辑
  }
}

该限流方案完美适配Taocarts集群部署架构,所有服务器节点共享Redis限流数据,无单点失效问题。可针对不同接口精细化配置防护规则,有效拦截恶意刷接口、爬虫高频抓取、恶意刷单等行为,保护服务器与数据库资源,大幅提升跨境站点抗攻击能力,是商用跨境系统必备的安全防护方案。

相关推荐
啦啦啦啦啦zzzz2 小时前
redis的持久化操作和主从复制与集群的关系及其应用
数据库·redis
大囚长2 小时前
大模型服务端如何命中缓存
java·人工智能·缓存·dubbo
IT策士2 小时前
Redis 从入门到精通:分片之道 —— Redis Cluster
数据库·redis·缓存
189228048612 小时前
NV114固态MT29F16T08EWLEHD6-MES:E
人工智能·算法·缓存·性能优化
AOwhisky2 小时前
学习自测与解析:Redis系列第一期与第二期核心知识点详解
运维·数据库·redis·学习·云计算
kishu_iOS&AI3 小时前
LLM —— Milvmus向量数据库
数据库·人工智能·milvus
名不经传的养虾人3 小时前
从0到1:企业级AI项目迭代日记 Vol.46|三个检索源、缓存限流、深度整合——联网检索一日冲刺
数据库·人工智能·agent·ai编程·ai工作流·企业ai
BugShare3 小时前
Mac 上原生开发的开源免费、尽享丝滑数据库工具
数据库·macos·开源
Java爱好狂.3 小时前
阿里1658页2026最新Java面试题总结(含答案)
数据库·redis·程序员·java面试·java面试题·java编程·java八股文