# 限流中间件 **本文引用的文件** - [server/src/middleware/rate-limiter.ts](file://server/src/middleware/rate-limiter.ts) - [server/src/services/redis.service.ts](file://server/src/services/redis.service.ts) - [server/src/middleware/usageLimit.ts](file://server/src/middleware/usageLimit.ts) - [server/src/middleware/errorHandler.ts](file://server/src/middleware/errorHandler.ts) - [server/src/types/index.ts](file://server/src/types/index.ts) - [server/src/app.ts](file://server/src/app.ts) - [server/src/modules/tts/tts.controller.ts](file://server/src/modules/tts/tts.controller.ts) - [server/src/modules/auth/auth.controller.ts](file://server/src/modules/auth/auth.controller.ts) ## 目录 1. [简介](#简介) 2. [项目结构](#项目结构) 3. [核心组件](#核心组件) 4. [架构总览](#架构总览) 5. [详细组件分析](#详细组件分析) 6. [依赖关系分析](#依赖关系分析) 7. [性能考虑](#性能考虑) 8. [故障排查指南](#故障排查指南) 9. [结论](#结论) 10. [附录](#附录) ## 简介 本文件为 AI 有声书生成平台的限流中间件综合文档,围绕基于 rate-limiter-flexible 的令牌桶限流实现,系统阐述以下内容: - 限流算法与策略选择:令牌桶与漏桶的对比、在本项目中的取舍与实现细节 - 限流规则设计:按 IP、按用户、按 API 接口等多维限流策略 - 配置参数与调优:阈值、时间窗口、封锁时长、突发处理 - 实现示例:在不同场景下的应用方法、监控与限流触发处理 - 与 Redis 的集成:高并发下的性能优化与降级策略 ## 项目结构 限流相关代码主要分布在以下位置: - 限流中间件:server/src/middleware/rate-limiter.ts - 使用量限流中间件:server/src/middleware/usageLimit.ts - Redis 服务:server/src/services/redis.service.ts - 错误处理:server/src/middleware/errorHandler.ts - 类型定义(会员配额):server/src/types/index.ts - 应用入口与路由注册:server/src/app.ts - 控制器示例:server/src/modules/tts/tts.controller.ts、server/src/modules/auth/auth.controller.ts ```mermaid graph TB subgraph "应用层" APP["应用入口
server/src/app.ts"] ROUTER["路由注册
各模块控制器"] end subgraph "中间件层" RL["限流中间件
server/src/middleware/rate-limiter.ts"] USAGELIMIT["用量限流中间件
server/src/middleware/usageLimit.ts"] ERR["错误处理中间件
server/src/middleware/errorHandler.ts"] end subgraph "服务层" REDIS["Redis 服务
server/src/services/redis.service.ts"] TYPES["类型与配额
server/src/types/index.ts"] end APP --> ERR APP --> RL APP --> USAGELIMIT APP --> ROUTER RL --> REDIS USAGELIMIT --> TYPES ``` 图表来源 - [server/src/app.ts:1-190](file://server/src/app.ts#L1-L190) - [server/src/middleware/rate-limiter.ts:1-120](file://server/src/middleware/rate-limiter.ts#L1-L120) - [server/src/middleware/usageLimit.ts:1-66](file://server/src/middleware/usageLimit.ts#L1-L66) - [server/src/services/redis.service.ts:1-274](file://server/src/services/redis.service.ts#L1-L274) - [server/src/types/index.ts:1-124](file://server/src/types/index.ts#L1-L124) 章节来源 - [server/src/app.ts:1-190](file://server/src/app.ts#L1-L190) ## 核心组件 - 限流中间件(令牌桶):基于 rate-limiter-flexible,支持内存与 Redis 两种存储后端,自动降级;提供通用限流中间件工厂与若干内置策略(API 全局、登录、短信、TTS、上传)。 - 使用量限流中间件:基于会员等级的每日次数与字数配额,结合数据库进行每日重置与校验。 - Redis 服务:提供连接管理、可用性检测、基础读写能力,作为限流器持久化存储。 - 错误处理:统一捕获限流与业务异常,返回标准响应格式。 - 类型与配额:定义会员等级与配额映射,支撑使用量限流。 章节来源 - [server/src/middleware/rate-limiter.ts:1-120](file://server/src/middleware/rate-limiter.ts#L1-L120) - [server/src/middleware/usageLimit.ts:1-66](file://server/src/middleware/usageLimit.ts#L1-L66) - [server/src/services/redis.service.ts:1-274](file://server/src/services/redis.service.ts#L1-L274) - [server/src/middleware/errorHandler.ts:1-67](file://server/src/middleware/errorHandler.ts#L1-L67) - [server/src/types/index.ts:114-124](file://server/src/types/index.ts#L114-L124) ## 架构总览 限流中间件通过 Redis 或内存实现令牌桶算法,对请求进行消费与拒绝;使用量限流中间件则在业务层对用户每日次数与字数进行配额控制。两者可组合使用,形成“网络层限流 + 业务层配额”的双重保护。 ```mermaid sequenceDiagram participant C as "客户端" participant A as "应用入口
app.ts" participant RL as "限流中间件
rate-limiter.ts" participant RS as "Redis 服务
redis.service.ts" participant U as "使用量限流中间件
usageLimit.ts" participant CTRL as "控制器
tts.controller.ts" C->>A : "HTTP 请求" A->>RL : "进入限流中间件" RL->>RS : "consume(key, 1)" alt "Redis 可用" RS-->>RL : "允许/拒绝" else "Redis 不可用" RL-->>RL : "内存限流器" end RL-->>A : "允许继续或返回 429" A->>U : "进入使用量限流中间件" U-->>A : "允许继续或抛出配额错误" A->>CTRL : "转发到控制器" CTRL-->>C : "业务响应" ``` 图表来源 - [server/src/app.ts:62-129](file://server/src/app.ts#L62-L129) - [server/src/middleware/rate-limiter.ts:49-72](file://server/src/middleware/rate-limiter.ts#L49-L72) - [server/src/services/redis.service.ts:43-45](file://server/src/services/redis.service.ts#L43-L45) - [server/src/middleware/usageLimit.ts:7-49](file://server/src/middleware/usageLimit.ts#L7-L49) - [server/src/modules/tts/tts.controller.ts:52-127](file://server/src/modules/tts/tts.controller.ts#L52-L127) ## 详细组件分析 ### 限流中间件(令牌桶) - 算法与策略 - 采用令牌桶(Token Bucket)思想,通过 consume(key, 1) 对每个请求进行扣减。 - 当 Redis 可用时使用 RateLimiterRedis,否则回退到 RateLimiterMemory。 - 支持自定义 keyGenerator,便于按 IP、用户 ID、API 名称等维度区分限流键。 - 关键配置项 - points:时间窗口内的配额(令牌数) - duration:时间窗口(秒) - blockDuration:封禁时长(秒),默认 duration*2 - keyGenerator:自定义键生成函数 - 内置策略 - API 全局限流:按 IP 维度,每分钟 100 次 - 登录接口限流:按 IP 维度,每分钟 5 次,封禁 5 分钟 - 短信发送限流:每分钟 1 次,每小时 5 次,封禁 1 小时 - TTS 生成限流:按用户维度,每分钟 20 次 - 文件上传限流:按用户维度,每分钟 10 次 - 触发处理 - 拒绝时设置 Retry-After 响应头,并返回 429 与 retryAfter 字段 ```mermaid flowchart TD Start(["进入限流中间件"]) --> GenKey["生成限流键
keyGenerator(ctx) 或 ctx.ip"] GenKey --> ChooseStore{"Redis 可用?"} ChooseStore --> |是| UseRedis["使用 RateLimiterRedis"] ChooseStore --> |否| UseMemory["使用 RateLimiterMemory"] UseRedis --> Consume["consume(key, 1)"] UseMemory --> Consume Consume --> Allowed{"是否允许?"} Allowed --> |是| Next["继续下一个中间件/控制器"] Allowed --> |否| Reject["设置 Retry-After
返回 429"] ``` 图表来源 - [server/src/middleware/rate-limiter.ts:20-72](file://server/src/middleware/rate-limiter.ts#L20-L72) - [server/src/services/redis.service.ts:43-45](file://server/src/services/redis.service.ts#L43-L45) 章节来源 - [server/src/middleware/rate-limiter.ts:1-120](file://server/src/middleware/rate-limiter.ts#L1-L120) ### 使用量限流中间件(按用户/会员等级) - 设计思路 - 基于会员等级的每日次数与字数配额,每日重置使用次数。 - 在业务流程中对 TTS 文本长度进行字数校验,避免超配额生成。 - 关键逻辑 - usageLimitMiddleware:加载用户信息,重置每日使用次数,校验次数配额 - checkWordLimit:在生成环节对文本字数进行校验 - 配额映射 - 免费用户:每日 3 次、5000 字 - 月卡用户:每日 20 次、50000 字 - 年卡用户:无限制 ```mermaid flowchart TD Enter(["进入使用量限流中间件"]) --> HasUser{"是否登录?"} HasUser --> |否| AllowGuest["设置无限制配额
继续"] HasUser --> |是| LoadUser["查询用户信息"] LoadUser --> ResetDaily{"是否跨日?"} ResetDaily --> |是| UpdateDaily["重置每日使用次数"] ResetDaily --> |否| SkipReset["跳过重置"] UpdateDaily --> CheckDaily["校验每日次数配额"] SkipReset --> CheckDaily CheckDaily --> DailyOK{"次数未超?"} DailyOK --> |是| SaveQuota["保存配额到 ctx.state"] DailyOK --> |否| ThrowDaily["抛出配额超限错误"] SaveQuota --> Next["继续下一个中间件/控制器"] ``` 图表来源 - [server/src/middleware/usageLimit.ts:7-49](file://server/src/middleware/usageLimit.ts#L7-L49) - [server/src/types/index.ts:120-124](file://server/src/types/index.ts#L120-L124) 章节来源 - [server/src/middleware/usageLimit.ts:1-66](file://server/src/middleware/usageLimit.ts#L1-L66) - [server/src/types/index.ts:114-124](file://server/src/types/index.ts#L114-L124) ### Redis 集成与降级 - 连接与可用性 - RedisService 提供连接、可用性检测、基础读写与错误日志 - isAvailable() 用于限流器选择 Redis 或内存后端 - 性能与可靠性 - Redis 可用时使用分布式限流,保证多实例一致性 - Redis 不可用时自动降级为内存限流,避免服务中断 ```mermaid classDiagram class RedisService { +isAvailable() boolean +get(key) Promise +set(key, value, ttl) Promise +del(key) Promise +incr(key) Promise +expire(key, seconds) Promise +exists(key) Promise +testConnection() Promise +disconnect() Promise } class RateLimiterRedis { +consume(key, points) Promise } class RateLimiterMemory { +consume(key, points) Promise } RedisService <.. RateLimiterRedis : "提供存储客户端" RedisService <.. RateLimiterMemory : "降级使用" ``` 图表来源 - [server/src/services/redis.service.ts:1-274](file://server/src/services/redis.service.ts#L1-L274) - [server/src/middleware/rate-limiter.ts:20-43](file://server/src/middleware/rate-limiter.ts#L20-L43) 章节来源 - [server/src/services/redis.service.ts:1-274](file://server/src/services/redis.service.ts#L1-L274) - [server/src/middleware/rate-limiter.ts:20-43](file://server/src/middleware/rate-limiter.ts#L20-L43) ### 错误处理与响应 - 统一错误处理中间件负责捕获限流与业务异常,返回标准化响应体 - 限流触发时设置 429 状态码与 retryAfter 字段,便于客户端重试控制 章节来源 - [server/src/middleware/errorHandler.ts:1-67](file://server/src/middleware/errorHandler.ts#L1-L67) - [server/src/middleware/rate-limiter.ts:60-71](file://server/src/middleware/rate-limiter.ts#L60-L71) ### 实际应用示例 #### TTS 生成接口的限流组合 - 场景:用户提交文本生成音频,需要同时满足网络层限流与业务层配额 - 步骤: 1) optionalAuth:可选认证,确保 ctx.state.user 可用 2) usageLimitMiddleware:检查用户每日次数与字数配额 3) ttsRateLimiter:按用户维度进行令牌桶限流 4) 业务处理:调用 TTS 服务并消耗配额 ```mermaid sequenceDiagram participant C as "客户端" participant R as "路由
tts.controller.ts" participant M1 as "optionalAuth" participant M2 as "usageLimitMiddleware" participant M3 as "ttsRateLimiter" participant S as "TTS 服务" C->>R : "POST /api/tts/generate" R->>M1 : "可选认证" M1-->>R : "设置 ctx.state.user" R->>M2 : "检查每日次数与字数配额" M2-->>R : "允许或抛出配额错误" R->>M3 : "令牌桶限流" M3-->>R : "允许或返回 429" R->>S : "生成音频" S-->>R : "返回结果" R-->>C : "响应" ``` 图表来源 - [server/src/modules/tts/tts.controller.ts:52-127](file://server/src/modules/tts/tts.controller.ts#L52-L127) - [server/src/middleware/rate-limiter.ts:105-110](file://server/src/middleware/rate-limiter.ts#L105-L110) - [server/src/middleware/usageLimit.ts:7-49](file://server/src/middleware/usageLimit.ts#L7-L49) 章节来源 - [server/src/modules/tts/tts.controller.ts:52-127](file://server/src/modules/tts/tts.controller.ts#L52-L127) #### 登录接口的限流 - 场景:防止暴力破解与短信轰炸 - 策略:按 IP 维度每分钟 5 次,封禁 5 分钟 - 应用:在 auth.controller.ts 的登录路由上挂载 loginRateLimiter 章节来源 - [server/src/middleware/rate-limiter.ts:83-91](file://server/src/middleware/rate-limiter.ts#L83-L91) - [server/src/modules/auth/auth.controller.ts:32-52](file://server/src/modules/auth/auth.controller.ts#L32-L52) ## 依赖关系分析 - 限流中间件依赖 Redis 服务进行分布式存储,Redis 不可用时回退内存 - 使用量限流中间件依赖数据库与类型定义,提供业务层配额控制 - 应用入口集中注册中间件与路由,控制中间件顺序与生效范围 ```mermaid graph LR RL["rate-limiter.ts"] --> RS["redis.service.ts"] RL --> EH["errorHandler.ts"] UL["usageLimit.ts"] --> EH UL --> TY["types/index.ts"] APP["app.ts"] --> RL APP --> UL APP --> ROUTERS["各模块控制器"] ``` 图表来源 - [server/src/middleware/rate-limiter.ts:1-120](file://server/src/middleware/rate-limiter.ts#L1-L120) - [server/src/services/redis.service.ts:1-274](file://server/src/services/redis.service.ts#L1-L274) - [server/src/middleware/usageLimit.ts:1-66](file://server/src/middleware/usageLimit.ts#L1-L66) - [server/src/middleware/errorHandler.ts:1-67](file://server/src/middleware/errorHandler.ts#L1-L67) - [server/src/types/index.ts:114-124](file://server/src/types/index.ts#L114-L124) - [server/src/app.ts:62-129](file://server/src/app.ts#L62-L129) 章节来源 - [server/src/app.ts:62-129](file://server/src/app.ts#L62-L129) ## 性能考虑 - Redis 连接池与重试策略 - RedisService 提供 retryStrategy,避免瞬时故障导致限流器不可用 - 建议在生产环境启用 Redis 集群或哨兵,提升可用性 - 限流键前缀与命名空间 - 使用 keyPrefix 避免键冲突,便于运维清理与统计 - 内存限流的适用场景 - 单实例或临时降级时使用,注意跨实例不一致问题 - 并发与延迟 - Redis 操作为 O(1),限流延迟主要来自网络往返;可通过批量操作与连接复用优化 - 窗口与突发 - 适当增大 points 与 duration 可平滑突发流量;blockDuration 用于阻断恶意攻击 ## 故障排查指南 - 限流频繁触发 - 检查 points 与 duration 是否过小,适当增大配额或窗口 - 查看 Redis 连接状态,确认 isAvailable() 返回值 - 客户端应读取 Retry-After 并进行指数退避重试 - Redis 不可用 - 确认连接参数与网络连通性 - 观察 RedisService 的连接事件日志,定位错误原因 - 使用量限流错误 - 确认用户登录状态与会员等级 - 检查每日重置逻辑与 lastUsageDate 字段 - 响应格式 - 统一由 errorHandler 中间件处理,确保 code、message、data 结构一致 章节来源 - [server/src/services/redis.service.ts:24-37](file://server/src/services/redis.service.ts#L24-L37) - [server/src/middleware/errorHandler.ts:3-24](file://server/src/middleware/errorHandler.ts#L3-L24) - [server/src/middleware/usageLimit.ts:26-37](file://server/src/middleware/usageLimit.ts#L26-L37) ## 结论 本限流中间件以 rate-limiter-flexible 为基础,结合 Redis 实现分布式令牌桶限流,并提供内存降级与多种内置策略。配合使用量限流中间件,形成“网络层限流 + 业务层配额”的双层防护,既保障系统稳定性,又兼顾用户体验。建议在生产环境中启用 Redis 集群、合理配置限流参数,并完善监控与告警体系。 ## 附录 ### 限流配置参数与调优建议 - 通用参数 - points:时间窗口内允许的请求数 - duration:时间窗口(秒) - blockDuration:封禁时长(秒),默认 duration*2 - keyGenerator:自定义键生成函数,支持按 IP、用户、API 等维度 - 调优建议 - 全局限流:API 全局每分钟 100 次,适合开放接口 - 登录接口:每分钟 5 次,封禁 5 分钟,平衡安全与体验 - 短信发送:每分钟 1 次,每小时 5 次,封禁 1 小时,防刷 - TTS 生成:按用户维度每分钟 20 次,结合会员等级动态调整 - 文件上传:按用户维度每分钟 10 次,避免资源滥用 章节来源 - [server/src/middleware/rate-limiter.ts:74-119](file://server/src/middleware/rate-limiter.ts#L74-L119) ### 限流规则设计思路 - 按 IP 限流:适用于匿名接口与敏感操作(登录、短信) - 按用户限流:适用于付费功能(TTS、上传),体现用户价值 - 按 API 限流:针对热点接口进行精细化控制 - 组合策略:网络层限流(令牌桶)+ 业务层配额(次数/字数) 章节来源 - [server/src/middleware/rate-limiter.ts:54-56](file://server/src/middleware/rate-limiter.ts#L54-L56) - [server/src/middleware/rate-limiter.ts:80-81](file://server/src/middleware/rate-limiter.ts#L80-L81) - [server/src/middleware/rate-limiter.ts:90-91](file://server/src/middleware/rate-limiter.ts#L90-L91) - [server/src/middleware/rate-limiter.ts:100-101](file://server/src/middleware/rate-limiter.ts#L100-L101) - [server/src/middleware/rate-limiter.ts:109-110](file://server/src/middleware/rate-limiter.ts#L109-L110) - [server/src/middleware/rate-limiter.ts:118-119](file://server/src/middleware/rate-limiter.ts#L118-L119) ### 监控与可观测性建议 - 指标采集:记录 429 次数、Redis 命中率、平均限流延迟 - 告警阈值:当 429 次数超过基线一定比例时触发告警 - 日志审计:记录被拒绝的请求键与原因,便于定位攻击源 [本节为通用建议,无需列出章节来源]