架构设计
后端基础设施与运行约束
总结后端在租户上下文、缓存、限流、任务、文件、审计、配置和可观测性上的基础设施规则。
这页的定位
前面的模块边界页主要解决“代码应该放哪里”,这一页解决的是另一个更容易踩坑的问题:后端公共基础设施应该怎么统一接入,哪些约束不能各写各的。
如果这些东西不统一,项目会很快出现:
- 每个模块自己管理租户上下文
- 每个模块自己发明缓存 key
- 每个模块自己决定日志字段和异常格式
- 异步任务、文件处理、限流、审计没有共识
这类分裂短期不明显,长期维护成本极高。
租户上下文
租户上下文是一级上下文,不是附属信息。一个有效请求在认证后至少应建立:
tenantIdtenantCodetenantStatususerIdroleSetpermissionSnapshotVersion
为什么这很重要
租户隔离不只影响数据库查询,还会影响:
- Redis 缓存
- 文件路径
- 日志
- 任务
- 限流
- 审计
如果只有数据库层带 tenant_id,其他层没有同步隔离,问题仍然会出现。
数据访问约束
- 基础单表能力可以交给统一数据访问层
- 复杂查询优先手写可控 SQL
- 租户级查询必须自动附带租户维度
- 列表查询必须分页
- 高频列表必须围绕真实查询路径设计索引
- 批量更新和删除要防止全表误操作
不要把“先跑通”当成长期数据访问方案。
缓存体系
推荐按两层理解:
- 本地热点缓存:极高频、低容量、稳定只读元数据
- Redis 分布式缓存:会话、权限快照、租户配置、菜单树、字典项、热点查询结果、任务状态
缓存 key 至少要明确这些维度中的若干项:
- 环境
- 模块
- 租户
- 用户
- 版本
典型失效场景
以下变更应触发缓存失效或版本刷新:
- 用户角色变更
- 菜单或权限变更
- 租户切换
- 配置修改
- 字典更新
- 用户移出租户
- 租户停用
限流与防刷
至少应该支持这些维度:
- IP
- 用户
- 租户
- 接口
- 客户端
- 全局
尤其要保护这些动作:
- 登录
- 导出
- 提交任务
- 状态切换
- 高风险写操作
这里建议和幂等、防重复提交一起设计,而不是分别零散补丁。
异步任务
统一任务中心更适合承载:
- 导入导出
- 报表生成
- 批量消息
- 批量授权
- 文件处理
- 同步任务
- 定时汇总
一个合格的任务对象至少应包含:
- 任务创建信息
- 状态
- 结果
- 失败原因
- 重试次数
- 执行日志
- 取消能力
tenantIduserId
文件能力
文件能力必须平台化,而不是由各业务模块各自维护一套上传逻辑。统一文件中心至少要负责:
- 上传
- 下载
- 删除
- 元数据记录
- 配额校验
- 访问控制
对象存储路径建议按这些维度分层:
- 环境
- 租户
- 业务模块
- 日期
私有文件默认不应裸链访问,更推荐预签名或受控下载接口。
日志与审计
应用日志
应用日志至少应带上这些上下文:
traceIdrequestIdtenantIduserId- 请求路径
- 耗时
- 结果码
操作审计
以下动作应重点进入审计:
- 用户管理
- 角色分配
- 权限调整
- 租户切换
- 配置修改
- 导入导出
- 敏感状态变更
安全日志
安全相关动作建议单独记录:
- 登录成功
- 登录失败
- 登出
- 刷新 token
- 账号锁定
- 权限拒绝
脱敏
日志不应直接记录:
- 密码
- 完整 token
- 完整手机号
- 完整身份证号
配置管理
配置至少可以分成三层:
- 环境配置
- 平台配置
- 租户配置
配置读取应收口到统一配置能力,而不是各模块自己查表、自己拼缓存。敏感配置应支持:
- 加密存储
- 变更审计
- 明确作用域
可观测性
至少建议有这些观察面:
- HTTP 请求量、错误率、耗时
- JVM、GC、线程池、CPU
- 数据库连接池、慢 SQL
- Redis 命中率和延迟
- 任务成功率和失败率
- 租户级流量和资源消耗
如果链路已经跨模块、跨任务、跨文件处理,就更需要稳定的追踪链路,而不是只靠文本日志猜测。
高可靠策略
- 主链路优先保护
- 弱依赖允许降级,不要拖垮主业务
- 外部依赖应有熔断或隔离
- 所有外部访问要设置明确超时
目标不是“所有事情都成功”,而是“即使一部分事情失败,主系统也不要整体失控”。
开发红线
- 不要让业务代码各自手工拼长期租户隔离方案
- 不要让每个模块自己定义缓存 key 体系
- 不要把导入导出做成大同步阻塞请求
- 不要把核心写操作做成无审计
- 不要把异常堆栈原样返回给前端
- 不要把文件直接落本地目录当成正式生产方案