本文引用的文件
本文件面向AI有声书生成平台的中间件体系,系统性阐述Koa.js中间件在请求生命周期中的设计理念与执行顺序,并结合平台实际实现,深入解析认证、安全、速率限制、缓存、性能监控、使用配额等中间件的功能、配置与协作关系。文档同时提供中间件开发指南、调试技巧与性能优化建议,帮助开发者在保证安全性与稳定性的同时,提升系统的可维护性与扩展性。
中间件体系位于服务端源码的中间层,围绕Koa应用实例进行装配,覆盖全局错误处理、日志、安全、限流、缓存、性能监控以及业务侧的使用配额控制。应用入口负责按序注册中间件与路由,确保中间件链路的正确性与一致性。
graph TB
subgraph "应用入口"
APP["app.ts<br/>创建Koa实例与Router"]
end
subgraph "全局中间件"
EH["errorHandler.ts<br/>统一错误处理"]
SEH["sentryErrorHandler.ts<br/>Sentry错误捕获"]
PM["performance.ts<br/>性能监控"]
RL["requestLogger.ts<br/>请求日志"]
HTTPL["logger.service.ts<br/>Winston HTTP日志"]
SEC["security.ts<br/>XSS/SQL注入/脱敏"]
CORS["app.ts<br/>CORS跨域"]
BODY["app.ts<br/>koa-body解析"]
end
subgraph "业务中间件"
AUTH["auth.ts<br/>认证/可选认证"]
USAGE["usageLimit.ts<br/>使用次数/字数限制"]
RATE["rate-limiter.ts<br/>通用限流器"]
CACHE["cache.ts<br/>缓存/清除缓存"]
end
subgraph "服务层"
REDIS["redis.service.ts<br/>Redis连接与操作"]
SENTRY["sentry.service.ts<br/>错误监控"]
end
APP --> EH --> SEH --> PM --> RL --> HTTPL --> SEC --> CORS --> BODY
SEC --> CACHE
CACHE --> REDIS
AUTH --> USAGE --> RATE
RATE --> REDIS
SEH --> SENTRY
图表来源
章节来源
章节来源
中间件在Koa应用中的装配顺序决定了请求的处理流程。下图展示了关键中间件的执行顺序与职责边界:
sequenceDiagram
participant C as "客户端"
participant A as "Koa应用(app.ts)"
participant EH as "错误处理"
participant SEH as "Sentry错误处理"
participant PM as "性能监控"
participant RL as "请求日志"
participant HTTPL as "Winston日志"
participant SEC as "安全中间件"
participant CORS as "CORS"
participant BODY as "Body解析"
participant R as "路由"
C->>A : "HTTP请求"
A->>EH : "进入中间件链"
EH->>SEH : "继续链路"
SEH->>PM : "继续链路"
PM->>RL : "继续链路"
RL->>HTTPL : "继续链路"
HTTPL->>SEC : "继续链路"
SEC->>CORS : "继续链路"
CORS->>BODY : "继续链路"
BODY->>R : "匹配路由"
R-->>C : "响应"
note over A,EH : "异常在EH中统一捕获并格式化"
图表来源
使用示例
在路由中直接挂载强制认证中间件,或在开放接口使用可选认证中间件。
flowchart TD
Start(["进入认证中间件"]) --> CheckAuth["检查是否启用强制认证"]
CheckAuth --> |未启用| InjectTest["注入测试用户到ctx.state.user"]
InjectTest --> Next1["调用next()"]
CheckAuth --> |启用| GetHeader["读取Authorization头"]
GetHeader --> HasHeader{"存在且格式正确?"}
HasHeader --> |否| ThrowUnauthorized["抛出未授权错误"]
HasHeader --> |是| VerifyToken["验证JWT"]
VerifyToken --> Valid{"验证通过?"}
Valid --> |是| InjectUser["注入用户信息到ctx.state.user"]
InjectUser --> Next2["调用next()"]
Valid --> |否| ThrowInvalid["抛出未授权错误"]
Next1 --> End(["结束"])
Next2 --> End
ThrowUnauthorized --> End
ThrowInvalid --> End
图表来源
章节来源
使用示例
在路由中可按需组合使用XSS与SQL注入防护,或仅启用脱敏中间件。
flowchart TD
Start(["进入安全中间件"]) --> XSS["递归清理请求体与查询参数中的XSS"]
XSS --> SetHeaders["设置安全响应头"]
SetHeaders --> Next1["调用next()"]
Next1 --> SQLCheck["扫描参数中的SQL注入模式"]
SQLCheck --> Found{"发现注入?"}
Found --> |是| Reject["返回400并终止请求"]
Found --> |否| Sensitive["对响应体进行敏感数据脱敏"]
Sensitive --> End(["结束"])
Reject --> End
图表来源
章节来源
使用示例
在高频接口上叠加全局限流与业务限流,确保系统稳定。
flowchart TD
Start(["进入限流中间件"]) --> GenKey["生成限流键(可自定义)"]
GenKey --> Consume["尝试消费1个配额"]
Consume --> Allowed{"配额充足?"}
Allowed --> |是| Next["调用next()放行请求"]
Allowed --> |否| Block["设置Retry-After并返回429"]
Next --> End(["结束"])
Block --> End
图表来源
章节来源
常用缓存配置
用户信息缓存、音色列表缓存、书籍详情缓存、热门书籍缓存、会员权益缓存等。
flowchart TD
Start(["进入缓存中间件"]) --> CheckRedis["检查Redis可用性"]
CheckRedis --> |不可用| Next["跳过缓存,直接next()"]
CheckRedis --> |可用| GenKey["生成缓存键(可自定义)"]
GenKey --> TryGet["尝试从Redis获取缓存"]
TryGet --> Hit{"命中?"}
Hit --> |是| ReturnCache["设置X-Cache=HIT并返回缓存"]
Hit --> |否| Exec["执行请求"]
Exec --> StatusOK{"状态200且有body?"}
StatusOK --> |是| SaveCache["缓存响应(带TTL)并设置X-Cache=MISS"]
StatusOK --> |否| SkipCache["不缓存"]
SaveCache --> End(["结束"])
SkipCache --> End
ReturnCache --> End
Next --> End
图表来源
章节来源
使用示例
在生产环境开启性能监控,结合日志与告警系统观察趋势。
flowchart TD
Start(["进入性能监控中间件"]) --> MarkStart["记录开始时间与端点标识"]
MarkStart --> Next["调用next()执行请求"]
Next --> Calc["计算耗时并更新全局与端点指标"]
Calc --> Slow{"超过慢请求阈值?"}
Slow --> |是| Warn["记录慢请求日志并设置X-Response-Time"]
Slow --> |否| SetHeader["设置X-Response-Time"]
Calc --> Catch["捕获异常并增加错误计数"]
Warn --> End(["结束"])
SetHeader --> End
Catch --> End
图表来源
章节来源
使用示例
在TTS生成接口中先执行使用配额检查,再进行字数校验与业务处理。
flowchart TD
Start(["进入使用配额中间件"]) --> HasUser{"是否存在用户ID?"}
HasUser --> |否| InjectUnlimited["注入无限制配额并next()"]
HasUser --> |是| LoadUser["查询用户信息并重置当日使用"]
LoadUser --> CheckDaily{"日使用次数未超限?"}
CheckDaily --> |否| ThrowQuota["抛出使用次数超限错误"]
CheckDaily --> |是| InjectQuota["注入用户配额与用户信息并next()"]
InjectUnlimited --> End(["结束"])
InjectQuota --> End
ThrowQuota --> End
图表来源
章节来源
使用示例
在中间件或控制器中抛出自定义错误,由统一中间件处理并记录日志。
sequenceDiagram
participant M as "任意中间件/控制器"
participant EH as "统一错误处理"
participant SEH as "Sentry错误处理"
participant LOG as "日志服务"
M->>M : "执行业务逻辑"
M-->>M : "抛出自定义错误"
M->>EH : "进入错误处理中间件"
EH->>LOG : "记录错误日志"
EH-->>M : "返回标准化错误响应"
M->>SEH : "进入Sentry错误处理中间件"
SEH-->>M : "捕获并上报Sentry"
SEH-->>M : "重新抛出原始错误"
图表来源
章节来源
循环依赖
中间件之间无循环依赖,遵循单向链式调用。
graph TB
AUTH["auth.ts"] --> CFG["config/index.ts"]
AUTH --> TYPES["types/index.ts"]
USAGE["usageLimit.ts"] --> TYPES
USAGE --> PRISMA["prisma(外部)"]
RATE["rate-limiter.ts"] --> REDIS["redis.service.ts"]
CACHE["cache.ts"] --> REDIS
SEC["security.ts"] --> TYPES
EH["errorHandler.ts"] --> TYPES
SEH["sentry.service.ts"] --> EH
RL["requestLogger.ts"] --> LOG["logger.service.ts"]
PM["performance.ts"] --> APP["app.ts"]
APP --> ROUTES["各模块控制器"]
图表来源
章节来源
章节来源
本中间件体系以Koa中间件链为核心,围绕认证、安全、限流、缓存、性能监控与使用配额构建了完整的请求生命周期保障机制。通过清晰的职责划分、可配置的参数与完善的错误处理,平台能够在保证安全性与稳定性的同时,提供良好的扩展性与可观测性。建议在生产环境中结合Redis、Sentry与日志系统,持续优化中间件顺序与配置,以获得更优的用户体验与运维效率。
章节来源