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

相关推荐
Bioinfo Guy3 小时前
高分Panel复现系列|转录因子网络太乱?用模块框把重点圈出来
数据库·生物信息学·生信可视化
ltl4 小时前
Disaggregated DB 合集:Socrates、PolarDB、Taurus 的共同模式
数据库
Blossom i6 小时前
大数据预处理与采集实验一:使用Python操作MySQL数据库
数据库·mysql
雾时之林7 小时前
Linux--软件管理、源码包安装
linux·服务器·数据库
thesky1234567 小时前
智能体面试准备(二十六):Agent 成本工程——模型路由、缓存、预算控制与大小模型分工
缓存·llmops·智能体·模型路由·成本工程·预算控制·小模型分工
老纪的技术唠嗑局8 小时前
超级干货分享:中小企业使用 OceanBase 实践经验汇总
数据库
CLOUD ACE9 小时前
谷歌云代理|零售商Target 如何利用 Spanner Graph 提升零售发现体验并将数据库维护成本降低 50%
数据库·零售
AI大模型-小雄9 小时前
Codex写分页接口为什么越翻越慢?用Cursor Pagination解决重复与漏数据
大数据·数据库·elasticsearch·搜索引擎·chatgpt·后端开发·codex
少晓年9 小时前
从 MySQL 迁移到人大金仓 KingbaseES:完整指南与实践
数据库·mysql
SelectDB10 小时前
Apache Doris AI RAG 实战:从基础 RAG 到知识图谱增强的技术能力与选型
数据库