# 限流中间件
**本文引用的文件**
- [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 次数超过基线一定比例时触发告警
- 日志审计:记录被拒绝的请求键与原因,便于定位攻击源
[本节为通用建议,无需列出章节来源]