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限流数据,无单点失效问题。可针对不同接口精细化配置防护规则,有效拦截恶意刷接口、爬虫高频抓取、恶意刷单等行为,保护服务器与数据库资源,大幅提升跨境站点抗攻击能力,是商用跨境系统必备的安全防护方案。

相关推荐
凌虚44 分钟前
基于 PostgreSQL WAL 构建 CDC 系统:原理与工程实现
数据库·后端·postgresql
BullSmall1 小时前
PostgreSQL 14 pg_dumpall 完整备份指南
数据库·postgresql·oracle
一只枫林2 小时前
MySQL内、外连接知识点汇总
java·前端·数据库
暮暮祈安2 小时前
Celery 新手入门指南
java·数据库·python·flask·httpx
xiaowang1234shs3 小时前
怪兽轻断食技术深度测评:从断食计时引擎到AI识别算法的工程实践解析
数据库·人工智能·算法·macos·机器学习·p2p·visual studio
Quincy_Freak3 小时前
银河麒麟 aarch64 环境下轻量 SQLite 管理方案实践:SQLiteGo 落地体验
数据库·sqlite·sqlitego
灵机一物3 小时前
企业选型参考:2026 CXL 内存扩展方案六强测评与落地指南
服务器·网络·数据库·人工智能
秋风渡.3 小时前
MySQL_数据类型知识
数据库·mysql
Season4504 小时前
Redis命令 (generic即通用命令)
数据库·redis·bootstrap
liwulin05065 小时前
【ollama】自定义结构化输出
linux·前端·数据库·ollama