Web 系统后端通用架构规范 v1.0
文档信息
项目 内容 文档名称 Web 系统后端通用架构规范 文档版本 v1.0 作者 花海 创建日期 2026-08-06 更新日期 2026-08-06 适用范围 单体架构、模块化单体、微服务架构与分布式系统;多租户(SaaS)领域见关联文档《多租户与数据隔离规范》 文档描述:本规范定义 Web 系统后端架构层的全量工程契约,涵盖分层架构、错误码、常量管理、认证授权、远程调用韧性、缓存、消息队列、数据持久化、测试门禁、版本控制、资源安全及通用编码约束。本规范同时适用于单体架构、模块化单体、微服务架构与分布式系统,不绑定任何实现方与编程语言。所有后端系统模块必须遵守本规范。
目录
- 1 · 总览与适用范围
- 2 · 分层架构与模块组织
- 3 · 接口与扩展机制规范
- 4 · 错误码规范
- 5 · 常量分类统一管理
- 6 · 认证与授权规范
- 7 · 远程调用与韧性设计
- 8 · 缓存全生命周期规范
- 9 · 消息队列消费规范
- 10 · 数据访问与查询规范
- 11 · 测试与质量门禁
- 12 · API 设计规范
- 13 · 数据变更管理
- 14 · 资源池化配置
- 15 · 依赖安全与配置安全
- 16 · 通用编码约束
- 17 · 日志规范
- 18 · 指标与告警规范
- 19 · 部署与发布
- 20 · 镜像与 CI/CD
- 21 · 事务规范
- 22 · 文件与对象存储规范
- 23 · 定时任务与分布式调度规范
- 24 · 数据库备份与恢复(RTO/RPO)
- 25 · 应用层安全规范
- 26 · 架构审查红线(汇总)
- 附录 A · 参考实现(配置示例、公式与取舍讨论)
- 关联文档
1 · 总览与适用范围
1.1 规范层级
| 章节 | 主题 | 优先级 | 核心关注点 |
|---|---|---|---|
| 2 | 分层架构与模块组织 | 强制 | 按业务功能组织(Package by Feature) |
| 3 | 接口与扩展机制规范 | 强制 | 接口设计原则、SPI 扩展点、接口兼容性 |
| 4 | 错误码规范 | 强制 | 错误码注册表、跨模块透传、边界收敛 |
| 5 | 常量分类统一管理 | 强制 | 常量分层、分类前缀、业务状态集中定义 |
| 6 | 认证与授权规范 | 强制 | OAuth2.0、统一入口鉴权、RBAC 最小化 |
| 7 | 远程调用与韧性设计 | 强制 | 超时、重试、熔断、降级(外部系统/服务间) |
| 8 | 缓存全生命周期规范 | 强制 | 更新策略、穿透/雪崩防护 |
| 9 | 消息队列消费规范 | 强制 | ACK 策略、幂等、批量、顺序 |
| 10 | 数据访问与查询规范 | 强制 | 索引、深分页、慢 SQL 门禁 |
| 11 | 测试与质量门禁 | 强制 | 覆盖率阈值、测试环境隔离、契约测试 |
| 12 | API 设计规范 | 推荐 | 资源命名、HTTP 动词、幂等键、版本控制 |
| 13 | 数据变更管理 | 推荐 | 脚本命名(基线/版本)、DDL/DML 分类、数据归档 |
| 14 | 资源池化配置 | 推荐 | 连接池公式、线程池命名 |
| 15 | 依赖安全与配置安全 | 推荐 | OWASP、配置中心加密 |
| 16 | 通用编码约束 | 强制 | 时区、业务状态、空值 |
| 17 | 日志规范 | 强制 | 日志级别、脱敏、TraceId 链路追踪 |
| 18 | 指标与告警规范 | 强制 | Metrics、SLO、告警分级与响应时效 |
| 19 | 部署与发布 | 强制 | 环境划分、配置隔离、发布策略、健康检查 |
| 20 | 镜像与 CI/CD | 推荐 | 镜像构建、扫描、流水线门禁、环境递进 |
| 21 | 事务规范 | 强制 | 事务边界、分布式事务、本地事务表 |
| 22 | 文件与对象存储规范 | 强制 | 上传限制、签名 URL、防盗链、分片上传 |
| 23 | 定时任务与调度规范 | 强制 | 防重复执行、锁租约、超时重试、执行记录 |
| 24 | 数据库备份与恢复 | 强制 | RTO/RPO、备份节奏、校验、恢复演练 |
| 25 | 应用层安全规范 | 强制 | 注入防护、XSS、越权(水平/垂直) |
| 26 | 架构审查红线(汇总) | 强制 | Checklist |
| 附录 A | 参考实现(配置示例、公式与取舍讨论) | 参考 | 非强制条款,落地时参考;与正文冲突以正文为准 |
1.2 术语约定
- 模块:最小的业务组织单元。单体架构中为进程内模块;微服务架构中一个模块即一个服务。
- 调用:模块间的协作方式。单体架构中为进程内调用;微服务架构中为远程调用。
- 统一入口:对外的请求边界。单体架构中为入口中间件/过滤器;微服务架构中为 API 网关。
- 请求上下文:一次请求链路内共享的用户与链路信息。
语言中立性说明:本规范不绑定任何实现方与编程语言,但示例以 Java 生态为主(如
ThreadLocal、PreparedStatement、Optional、JSP/Thymeleaf、HikariCP)。其他语言按等价概念映射理解,例如:ThreadLocal→ Go 的context.Context、Python 的threading.local;PreparedStatement→ 各语言的参数化查询 API;Optional→ 各语言的可空/可选类型约定。示例仅为说明契约语义,非强制技术选型。
1.3 单体 vs 微服务适配表
同一架构原则在不同部署形态下的落地方式不同,本规范条款均已按通用原则表述,下表给出适配指引:
| 条款 | 单体 / 模块化单体 | 微服务 / 分布式 |
|---|---|---|
| §1.4 无状态 | 单实例可本地缓存(见 §8.4);多实例必须外置;Session 必须集中式存储 | 必须外置(分布式缓存/数据库/配置中心);Session 必须集中式存储 |
| §1.5 前后端分离 | 默认优先;后端只提供 API,认证优先 Token/OAuth2.0 | 默认优先;后端只提供 API,认证优先 Token/OAuth2.0 |
| §2 分层组织 | 同进程模块化,按业务域拆分包 | 业务域即服务,独立部署 |
| §3 接口与扩展 | 模块间面向接口协作,扩展点内置 | 面向接口 + SPI 扩展点 + 默认实现 |
| §4 错误码 | 模块间可共享错误码注册表;边界收敛由入口中间件完成 | 禁止跨服务引用错误码定义,只传 code;边界收敛由网关完成 |
| §5 常量 | 全局常量公共包共享;业务域常量仍禁止跨模块引用 | 全局常量下沉公共包;业务域常量禁止跨服务 import |
| §6 认证授权 | 入口中间件统一校验,进程内传递请求上下文;仅传统后端渲染场景可用 Session-Cookie | 网关统一校验,透传上下文头(X-User-Id 等);通常用 Token |
| §7 韧性设计 | 进程内调用无需超时/熔断;调用外部系统仍必须遵守本规范 | 服务间远程调用 + 外部系统调用均须遵守 |
| §8 缓存 | 单实例可用本地缓存;多实例部署仍按本规范 | 分布式缓存为主,本地缓存 TTL ≤ 分布式 TTL 的 1/3 |
| §9 消息队列 | 适用(解耦异步任务) | 适用(服务间事件驱动) |
| §10 数据访问 | 多模块共享数据库需约定模块间数据访问边界 | 服务独立库,禁止跨服务直连数据库 |
| §12 API 版本 | 适用 | 适用 |
| §13 数据变更 | 单一变更管线 | 每服务独立变更管线 |
| §14 资源池化 | 适用 | 适用 |
| §15 安全 | 适用 | 适用 |
| §16 编码约束 | 适用 | 适用 |
| §17 日志规范 | 单实例可本地日志;多实例需集中采集 | 必须集中采集 + TraceId 跨服务透传 |
| §18 指标与告警 | 单实例本地指标采集 + 基础告警 | 集中指标采集 + 指标大盘 + SLO 与告警分级 |
| §19 部署发布 | 全量发布为主;环境隔离仍需遵守 | 独立部署 + 蓝绿/灰度 + 健康检查 |
| §20 镜像与 CI/CD | 流水线全量构建 + 镜像管理 | 流水线构建 + 镜像扫描 + 环境递进部署 |
| §21 事务规范 | 进程内本地事务 | 分布式事务(Saga/TCC/本地事务表) |
| §22 文件存储 | 本地磁盘 + 服务器直出;需自行约束大小与清理 | 对象存储私有读写 + 签名 URL + 防盗链;大文件分片上传 |
| §23 定时任务 | 单实例本地调度;多实例需自行防重复 | 调度中心/选主 + 分布式锁租约;防重复、超时、重试、执行记录 |
| §24 备份恢复 | 本地全量备份,无校验无演练 | 全量 + 增量 + 日志归档按 RPO;异地保存、校验、定期恢复演练 |
| §25 应用层安全 | 适用 | 适用 |
| §26 红线汇总 | 适用 | 适用 |
1.4 全局无状态设计原则
本规范定义 Web 系统架构的最高层原则:不论单体还是微服务,模块/服务默认必须无状态。仅当存在性能极致敏感场景(如本地缓存热点数据、计算密集型中间结果)时,才允许保留状态,且必须显式声明并评估副作用。
1.4.1 无状态定义
模块/服务的任何请求处理不依赖本实例的内存状态,所有可变状态必须外置:
| 状态类型 | 外置方式 | 说明 |
|---|---|---|
| 用户会话 | 集中式存储(如 Redis、数据库) | 禁止存本实例内存 |
| 业务数据 | 数据库 / 分布式缓存 | 禁止本实例内存缓存(除允许场景) |
| 临时中间结果 | 分布式缓存 / 消息队列 | 禁止存本实例内存 |
| 配置 | 配置中心 | 禁止本地文件硬编码 |
1.4.2 允许有状态的场景
仅以下场景允许保留状态,且必须满足约束:
| 场景 | 允许状态 | 约束 |
|---|---|---|
| 性能极致敏感的热点数据 | 本地缓存 | TTL ≤ 分布式缓存 TTL 的 1/3,且写操作必须走分布式缓存(见 §8.4) |
| 计算密集型中间结果 | 本实例内存(如报表聚合) | 结果必须可重建,进程重启不丢失业务正确性 |
| 单实例部署的临时状态 | 本实例内存 | 仅限单实例,多实例部署时必须外置 |
禁止以"实现简单"为由保留状态。任何有状态设计必须经过架构评审,并在代码注释中显式标注 @Stateful 及原因。
1.4.3 无状态的收益
- 水平扩展:任意增减实例,无需考虑状态迁移。
- 故障恢复:实例崩溃后,新实例立即接管,无状态重建成本。
- 负载均衡:请求可路由到任意实例,无会话粘滞需求。
- 部署简单:蓝绿/灰度发布无需考虑状态同步。
1.4.4 架构审查红线
- ❌ 默认将有状态设计作为首选(如本地内存存会话)
- ❌ 以"实现简单"为由保留状态,未评估副作用
- ❌ 有状态设计未显式标注
@Stateful及原因 - ❌ 多实例部署仍用本实例内存存状态
- ❌ 前后端分离项目仍用后端渲染(如 JSP/Thymeleaf 直出页面)
- ❌ 前后端分离项目用 Session-Cookie 做认证(跨域/多端受限)
- ❌ 后端接口返回 HTML 片段而非 JSON 数据
- ✅ 默认无状态,状态外置到数据库/分布式缓存/配置中心
- ✅ 仅性能极致敏感场景允许有状态,且必须显式评审
1.5 前后端分离优先原则
本规范定义 Web 系统架构的第二层原则:项目架构优先考虑前后端分离。前后端分离与全局无状态原则(§1.4)相辅相成,是现代 Web 系统的默认架构模式。
1.5.1 前后端分离定义
| 维度 | 说明 |
|---|---|
| 职责划分 | 前端负责页面渲染与用户交互,后端只提供 API 接口 |
| 通信方式 | 前后端通过 HTTP API 通信,禁止后端直接渲染页面(如 JSP/Thymeleaf) |
| 部署方式 | 前端与后端独立部署,可独立扩展与发布 |
1.5.2 前后端分离 vs 传统后端渲染
两种架构模式的适用场景、认证模式与优先级对比见 附录 A.1(参考实现)。本规范默认采用前后端分离(见 §1.5.1 定义与 §1.5.4 认证关系)。
1.5.3 前后端分离的收益
- 多端复用:一套 API 支持 Web、App、小程序等多端。
- 独立扩展:前后端独立部署、独立扩缩容。
- 开发并行:前后端并行开发,接口契约先行(见 §11.2 契约测试)。
- 技术栈灵活:前端可独立演进技术栈,不受后端框架限制。
1.5.4 与认证模式的关系
前后端分离架构下,认证模式优先选择 Token / OAuth2.0:
- Token 无状态、自包含,适合 API 服务与多端场景。
- Session-Cookie 依赖 Cookie 与集中式 Session 存储,在跨域、多端场景下受限。
仅当满足以下全部条件时,才允许选择 Session-Cookie:
- 单体架构 + 后端渲染(非前后端分离)。
- 仅 Web 浏览器端,无 App/小程序等多端需求。
- 无跨域调用需求。
1.5.5 架构审查红线
- ❌ 前后端分离项目仍用后端渲染(如 JSP/Thymeleaf 直出页面)
- ❌ 前后端分离项目用 Session-Cookie 做认证(跨域/多端受限)
- ❌ 后端接口返回 HTML 片段而非 JSON 数据
- ✅ 默认前后端分离,后端只提供 API
- ✅ 前后端分离项目认证优先 Token / OAuth2.0
2 · 分层架构与模块组织
2.1 按业务功能组织(非分层平铺)
系统按业务功能组织,而非按技术分层平铺。同一业务域的相关代码聚合在一起,降低认知成本与变更影响面。单体架构下为同进程模块,微服务架构下模块即服务,包结构与职责划分保持一致。
<根命名空间>.<业务模块>
├── config // 配置装配
├── api/接入层 // 接口入口:仅做参数校验与转发
├── application/应用层 // 业务逻辑编排、事务边界
│ └── impl
├── domain/领域模型 // 贫血模型下的业务数据包(非 DDD 战术设计中的聚合根/实体概念)
│ ├── entity // 数据实体(与数据库表对应)
│ ├── vo // 视图对象
│ ├── dto // 传输对象
│ ├── repository/dao // 数据访问接口(非 DDD 仓储模式)
│ └── constants // 业务域常量
├── infrastructure/基础设施 // 外部系统调用、消息发送、缓存配置
├── utils // 工具类(无状态、线程安全)
└── exception // 自定义异常/错误码定义
非 DDD 声明:本规范采用贫血模型 + 分层架构(非 DDD 战术设计)。
domain目录仅为业务数据包(实体/VO/DTO/数据访问接口),不涉及 DDD 中的聚合根(Aggregate Root)、实体(Entity)、值对象(Value Object)等领域概念;repository指数据访问接口,非 DDD 仓储模式。
2.2 分层约束
| 层级 | 职责 | 禁止 |
|---|---|---|
| 接入层 | 参数校验、调用应用层、返回结果 | 写业务逻辑、直接操作数据访问层 |
| 应用层 | 业务编排、事务边界、抛出异常 | 跨模块依赖对方异常定义、裸拼接查询条件 |
| 数据访问层 | 数据读写 | 写业务判断、返回 null 不处理 |
| 基础设施层 | 外部系统调用封装、降级兜底 | 抛业务异常、透传用户凭证 |
2.3 模块间边界
- 模块之间只能通过公开接口协作,禁止绕过模块接口直接访问其内部数据(如直连其他模块的数据表)。
- 单体架构下,跨模块调用仍须遵守公开接口约束,防止模块耦合腐化。
- 微服务架构下,模块(服务)间只能通过远程调用协作,禁止共享数据库。
3 · 接口与扩展机制规范
本规范定义内部接口设计原则、扩展点(SPI)机制及接口兼容性约束。模块间协作与功能拓展必须通过接口完成,禁止实现级耦合与硬编码分支扩展。
3.1 接口设计原则
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 面向接口编程 | 模块依赖对方具体实现类 | 面向接口编程(依赖倒置),模块间只依赖接口,禁止依赖实现 |
| 接口隔离 | 大而全的上帝接口 | 接口隔离(ISP),按职责拆分小接口,避免无关依赖 |
| 接口粒度 | 接口过粗或过细失衡 | 接口粒度与业务用例对齐,方法单一职责 |
3.2 接口分层
- 接入层接口:对外 API(见 §12 API 设计规范),仅做参数校验与转发。
- 应用层接口:业务服务接口,模块内部对外的协作契约。
- 数据访问接口:仓储/DAO 接口,隔离数据访问实现。
- 扩展点接口:可插拔功能拓展的契约(见 §3.3)。
3.3 扩展点(SPI)机制
功能拓展必须通过定义扩展接口实现,禁止硬编码分支扩展。
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 扩展方式 | 业务代码 if-else 硬编码分支扩展 | 定义扩展接口(SPI),扩展实现类承载差异化逻辑 |
| 注册方式 | 扩展散落、无统一入口 | 统一扩展注册机制(注册表/配置声明),显式注册 |
| 默认实现 | 扩展点无默认实现,核心逻辑依赖扩展 | 扩展点必须提供默认实现,核心功能不因扩展缺失而失效 |
| 优先级 | 同类型扩展冲突无排序 | 支持优先级排序,按优先级生效,可覆盖默认实现 |
| 扩展隔离 | 扩展直接修改核心模块代码 | 扩展只能实现扩展接口,禁止修改核心模块代码 |
| 无状态 | 扩展实例携带状态 | 扩展实现默认无状态;若需状态,必须在扩展内部显式管理(如通过参数传递),禁止依赖实例级共享可变状态(见 §1.4) |
3.4 接口兼容性
- 对外接口:按 §12.5 兼容性约束,破坏性变更必须发新版本。
- 内部接口:变更须评估调用方影响,禁止静默破坏调用方。
- 扩展接口:发布即契约;新增方法兼容,删除/修改签名属破坏性变更,需走版本评审。
3.5 架构审查红线
- ❌ 模块依赖对方具体实现类(而非接口)
- ❌ 业务功能拓展用 if-else 硬编码分支
- ❌ 扩展点无默认实现,核心逻辑依赖扩展
- ❌ 扩展直接修改核心模块代码
- ❌ 扩展实例有状态
- ✅ 模块间面向接口编程
- ✅ 功能拓展走扩展接口 + 统一注册机制
- ✅ 扩展点有默认实现、可排序、无状态
4 · 错误码规范
本规范定义 Web 系统统一的错误码体系:格式、分类、传递契约、边界收敛策略,以及业务模块自定义错误码的指引。所有模块必须遵守本规范。
4.1 错误码格式
格式:E<大类>-<子类/域>-<3位编号>,共三段,如 E4-ORDER-001。
E4 - ORDER - 001
│ │ └── 3 位编号(段内递增,如 001/002...)
│ └── 子类(E1/E2/E3/E5)或 域(E4 业务域,由业务模块自定义)
└── 大类码(E1~E5)
- 成功码:
S0000,不参与 E 前缀分类。 - 未识别前缀按
E5(系统未知)兜底——安全失败原则,避免误判为可重试或客户端错误。
4.2 错误码分类表
| 前缀 | 大类 | 第二段 | 语义 | 默认 HTTP | 对外收敛后 HTTP | 日志级别 | 可重试 |
|---|---|---|---|---|---|---|---|
| E1 | 参数类 | 子类:PARAM/VALID/TYPE/FILE/RATE/HTTP | 缺参、类型错误、校验失败、文件内容非法、限流、方法不允许 | 400 | 200 | INFO | 否 |
| E2 | 权限类 | 子类:AUTH/TOKEN/PERM | 未认证、token 过期、无权限 | 401 | 200 | INFO | 否 |
| E3 | 基础设施类 | 子类:DB/CACHE/HTTP/THIRD/PAY/FILE/LOCK/SMS | 数据库、缓存、第三方调用、文件存储、锁获取失败 | 500 | 200 | ERROR | 是 |
| E4 | 业务域类 | 域:ORDER/USER/GOODS...(业务模块自定义,COMMON 为通用业务域) | 业务规则冲突、状态非法、资源不存在 | 422 | 200 | WARN | 否 |
| E5 | 系统未知类 | 子类:SYS/UNKNOWN | 未知异常、代码缺陷、兜底 | 500 | 200 | ERROR | 否 |
| S | 成功 | - | 操作成功 | 200 | 200 | - | - |
分层说明:"默认 HTTP"为模块间调用、内部服务间调用使用的真实 HTTP 状态码;"对外收敛后 HTTP"为面向外部客户端的统一入口响应收敛后的状态码(默认 200,见 §4.6)。两层状态码职责不同,不可混用。
4.2.1 子类 vs 域
- 子类:E1/E2/E3/E5 的第二段,是该大类下的细分(如 E3 下的 DB/CACHE/HTTP)。
- 域:E4 的第二段,是业务域(对应业务模块),由各业务模块自定义,避免与
COMMON冲突。
4.2.2 通用错误码参考表
| code | 场景 | 默认 HTTP(模块间/内部调用) |
|---|---|---|
| S0000 | 操作成功 | 200 |
| E5-SYS-000 | 系统未知异常(对外兜底码) | 500 |
| E5-SYS-001 | 通用服务器错误 | 500 |
| E5-SYS-002 | 服务不可用 | 503 |
| E1-PARAM-000 | 参数错误 | 400 |
| E1-PARAM-001 | 查询参数不能为空 | 400 |
| E2-AUTH-000 | 未认证 | 401 |
| E2-AUTH-001 | 凭证已过期 | 401 |
| E2-PERM-000 | 无权限 | 403 |
| E4-COMMON-000 | 资源不存在 | 404 |
| E4-COMMON-001 | 资源冲突 | 409 |
| E1-HTTP-000 | 方法不允许 | 405 |
| E1-RATE-000 | 请求过于频繁 | 429 |
| E3-LOCK-000 | 锁获取失败 | 423 |
说明:本表 HTTP 为模块间/内部调用的默认状态码;对外统一入口响应按 §4.6 收敛为 200。
内部专用码:
405(方法不允许)、423(WebDAV 扩展 Locked,锁获取失败)等状态码仅用于模块间/内部调用的语义表达,对外统一收敛为 200。423属 WebDAV 扩展而非通用 HTTP 标准,内部使用前须确认下游能正确解析;如无法解析,可用409(冲突)或500替代。
4.3 错误码解析机制
- 提供统一的错误码解析入口(错误码注册表 / 前缀解析器):任意模块收到错误码字符串即可推导大类,无需依赖对方模块的错误码定义。
- 解析能力至少包含:大类描述、默认 HTTP 状态、是否为客户端错误(客户端错误记 INFO,服务端错误记 ERROR)、是否可重试(仅 E3 基础设施类可重试)。
- 禁止在业务代码中自行对前缀做字符串判断(如
code.startsWith("E1")),必须统一走解析入口。
4.4 错误码定义契约
- 错误码必须使用枚举定义(显式声明
code + message),禁止散落裸字符串/数字;HTTP 状态由解析入口按前缀推导,需要精确状态时显式覆盖。 - 业务规则/资源类错误用
E4-<业务域>-<编号>;参数/权限类复用通用 E1/E2 子类。 - 错误码一经发布即视为对外契约,禁止修改已发布 code 的语义。
4.5 错误码传递契约(跨模块 / 跨服务)
4.5.1 传递契约
- 模块间只传递统一响应结构(
code字符串 +message+data),错误码原样透传。 - 单体架构:模块间可直接共享错误码注册表,但仍禁止模块 A 直接依赖模块 B 的错误码定义类(模块 B 的域错误码由模块 B 自行声明)。
- 微服务架构:禁止跨服务引用对方的错误码定义类,只传 code 字符串。
- 解析对方错误码统一走错误码解析入口,禁止自行写前缀判断。
- 未知错误码按 E5 兜底。
4.5.2 透传链路
上游抛出 E4-ORDER-001(订单不存在)
→ 全局异常处理按默认 422 响应
→ HTTP 422 + {"code":"E4-ORDER-001","message":"订单不存在","data":null}
→ 下游解析统一响应结构
→ 响应非成功 → 采用上游 HTTP 状态(否则按前缀推导)
→ 构造等价业务异常并抛出
→ 下游全局异常处理响应 HTTP 422 + {"code":"E4-ORDER-001",...}
4.5.3 调用方处理策略
| 上游响应 | 下游处理 |
|---|---|
| 2xx + 业务成功 | 正常返回 data |
| 2xx + 业务失败 | 错误码原样透传,httpStatus 按前缀推导 |
| 4xx/5xx + 标准响应结构 | 错误码原样透传,httpStatus 采用上游 HTTP 状态码 |
| 4xx/5xx + 非标准结构 | 抛通用调用异常,触发熔断降级 |
4.5.4 异步链路错误码传递
消息队列/事件等异步链路的错误码传递,与同步调用保持一致:
- 消息体中必须包含
code字段(如E4-ORDER-001),消费者按错误码解析入口推导语义。 - 消费者处理失败时,错误码随消息进入重试/死信队列,便于链路追踪与重放。
- 异步链路中禁止抛裸异常,必须转换为错误码后传递。
4.6 边界收敛策略
4.6.1 收敛规则
本节仅针对面向外部客户端的统一入口响应(出网响应)。模块间调用、内部服务间调用仍按 §4.2 错误码分类表使用真实 HTTP 状态码(E1→400、E2→401、E3→500、E4→422),不执行收敛;仅当响应经统一入口发给外部调用方时,才按本节收敛为
responseStatus(默认 200)。
统一入口(API 网关 / 入口中间件)对出网响应(发给外部调用方)做映射:
| 大类 | 策略 | 外部调用方看到 |
|---|---|---|
| E1/E2/E4 | 透传 | 原 code + 原 message(调用方需提示用户) |
| E3/E5 | 收敛隐藏 | E5-SYS-000 + "系统繁忙,请稍后重试"(隐藏内部细节) |
| S | 透传 | S0000 |
响应状态码统一收敛为 responseStatus(默认 200),业务结果由 body.code 表达——外部调用方不感知系统内部真实异常状态码。
例外场景:文件下载、文件流、长连接(SSE/WebSocket)、限流响应(429 + Retry-After,客户端需感知重试时机) 等非 JSON 响应场景,允许使用真实 HTTP 状态码表达结果(如下载失败返回 404/500),不受统一收敛约束。幂等冲突(§12.6)等业务正常路径仍收敛为 200。
4.6.2 配置项
统一入口错误码收敛的配置字段与参考示例见 附录 A.2(参考实现)。
4.7 统一响应结构
- 成功:
code=S0000,携带可选数据。 - 失败:
code=错误码+message+data=null。 - 接入层直接返回业务数据,由统一包装机制自动包成响应结构;业务失败通过异常机制统一拦截处理。
4.8 架构审查红线
- ❌ 跨模块/跨服务引用对方模块的错误码定义类
- ❌ 自行对错误码前缀做字符串判断
- ❌ 模块间传递非统一响应结构
- ✅ 模块间只传递 code 字符串,统一走解析入口
- ✅ 错误码发布后不可变更语义,新增只能追加
5 · 常量分类统一管理
本规范定义常量的分层存放、分类标识、命名契约及使用约束。所有魔法值(除数学
0/1外)必须具名化,禁止裸字符串/数字出现在业务代码中。
5.1 分层体系
常量按作用域分三层,与错误码的"全局 → 业务域 → 模块内"层级对齐:
| 层级 | 作用域 | 存放位置 | 变更控制 |
|---|---|---|---|
| 全局常量 | 跨模块共享 | 公共常量包 | 需架构评审,发布后保持向后兼容 |
| 业务域常量 | 模块内跨子模块 | 业务域常量包 | 模块 Owner 审批,code 一旦发布不可变更 |
| 模块内常量 | 模块私有 | 模块常量包 | 模块负责人自主,但禁止跨模块引用 |
5.2 分类维度(与错误码大类对齐)
| 分类 | 前缀 | 说明 | 对应错误码 | 典型场景 |
|---|---|---|---|---|
| 参数类 | PARAM_ | 校验阈值、默认值、正则、分页 | E1 | 最大分页、手机号正则 |
| 权限类 | AUTH_ | 角色码、权限点、凭证时效配置 | E2 | 凭证过期时间、密钥标识 |
| 基础设施类 | INFRA_ | 缓存 Key、消息 Topic、超时、重试 | E3 | 缓存前缀、调用读超时 |
| 业务域类 | BIZ_ | 业务状态值、业务规则阈值、计算系数 | E4 | 订单状态、库存扣减上限 |
| 系统类 | SYS_ | 框架配置、系统默认值、环境标识 | E5 | 环境标识、线程池命名前缀 |
说明:
SYS_类常量对应的异常若无法归类(不属于 E1~E4 任何已知大类),统一收敛至 E5 系统未知类兜底(见 §4.1)。
5.3 命名规范
5.3.1 格式
<分类前缀>_<业务域简写>_<具体含义>[_<属性>]
| 段 | 约束 |
|---|---|
| 分类前缀 | 必须为PARAM_ / AUTH_ / INFRA_ / BIZ_ / SYS_ 之一 |
| 业务域简写 | 与错误码 E4 域一致,如ORDER / USER / GOODS;全局常量用 COMMON |
| 具体含义 | 动名词组合,如MAX_PAGE_SIZE、STATUS_PENDING |
| 属性 | 可选,如_MILLIS、_PREFIX、_PATTERN |
5.3.2 正反示例
| 场景 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 分页大小 | MAX = 500 | PARAM_COMMON_MAX_PAGE_SIZE = 500 |
| 缓存前缀 | CACHE = "order" | INFRA_CACHE_ORDER_PREFIX = "web:order:v1:" |
| 订单状态 | STATUS = 0 | 见下方业务状态规范 |
| 凭证过期 | EXPIRE = 30 | AUTH_TOKEN_EXPIRE_MINUTES = 30 |
5.4 业务状态定义规范
术语说明:本规范统一术语——API 响应的错误码沿用"错误码"(Error Code,见 §4);业务实体生命周期状态(如订单状态 PENDING/PAID)统称为**"业务状态"**(Business Status),不再使用"状态码"一词指代。
业务状态必须集中定义,禁止用散落的裸 int/String 常量定义业务状态。
5.4.1 契约
- 业务状态必须使用枚举定义,显式声明
code + 描述,code一旦发布不可变更,新增状态只能追加。 - 业务状态存入数据库必须做映射:入库时映射为
code值存储,读取时按code反查枚举;严禁直接存枚举本身(枚举名或序列化对象)。 - 必须提供按
code反查业务状态的能力;查询到未知code时抛出明确的业务异常(而非静默返回默认值)。 - 同一业务状态集合只允许存在一份定义,禁止多处重复声明。
5.4.2 正反示例
✅ 推荐:集中定义,code 显式声明,带描述,支持反查与未知值校验
BizOrderStatus: PENDING("0","待支付") / PAID("1","已支付") / SHIPPED("2","已发货") ...
❌ 禁止:裸 int 状态散落各模块,无描述,无法反查
OrderConstants.STATUS_PENDING = 0
✅ 入库映射:DB 存 code 值(如 "0"),读取时反查枚举
DB: "0" → BizOrderStatus.of("0") → PENDING
❌ 禁止:直接存枚举本身(枚举名 PENDING 或序列化对象)
5.5 字符串拼接规范
含动态段的字符串(如缓存 Key web:user:v1:detail:{userId}、MQ Topic、日志标签)必须走常量模板 + 统一拼接,禁止业务代码散落手写拼接:
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 拼接位置 | 业务代码中散落"web:order:" + orderId | 拼接收敛到统一生成方法(如KeyBuilder),业务代码只调用方法名 |
| 模板定义 | 把含动态段的完整 Key 写成常量 | 常量只定义带占位符的静态模板(如web:order:v1:detail:{id}),动态段运行时注入 |
| 分隔符 | 混用:、_、- 无统一约定 | 默认统一用: 分隔段,段内用 _;不同场景类别可约定不同分隔符,但同一类别内必须一致 |
| 动态段校验 | 动态段为空/含非法字符直接拼接 | 拼接前校验动态段(非空、合法字符),校验失败抛业务异常 |
| 参数顺序 | 连续+ 拼接,参数顺序错乱难排查 | 用占位符模板显式声明参数位置,按序注入 |
| 可读性 | 拼接结果无业务语义、无法全局搜索 | 模板常量具名化(如INFRA_CACHE_ORDER_DETAIL),全链路可搜索与复用 |
说明:分隔符按场景类别约定——缓存 Key、业务字符串默认用
:分隔段;MQ Topic 等按 MQ 社区惯例可用-(见 §5.7 消息常量规范)。同一场景类别内必须全局一致,禁止混用。
占位符模板 + 统一生成方法的正反示例见 附录 A.10(参考实现)。
- 动态段(id、userId)禁止写入常量名或常量值,只作为参数传入生成方法。
- 含动态段字符串的生成统一收敛到基础设施层(如
KeyBuilder/TopicBuilder),业务层禁止自行拼接。 - 同一模板常量全局唯一,禁止多处重复定义等价拼接格式。
5.6 缓存 Key 规范
缓存 Key 必须走常量模板 + 统一生成方法,禁止在业务代码中拼接字符串(按 §5.5 字符串拼接规范执行)。
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 命名空间 | "user_" + userId | key = KeyBuilder.build(INFRA_CACHE_USER_DETAIL, userId) // → web:user:v1:detail:1001 |
| 版本控制 | 无版本,重构后冲突 | 必须带版本号web:<module>:v1:<biz>,版本段写在模板常量中 |
| TTL | 业务代码硬编码 | 常量定义 TTL,配置中心可覆盖 |
| 大 Key 前缀 | 无业务域隔离 | 必须包含模块名 + 业务域,如web:order:v1:detail:{id}(占位符见 §5.5) |
多租户场景:缓存 Key 必须包含租户维度,模板格式为
web:{tenantId}:<module>:v1:<biz>:{id},按 §5.5 字符串拼接规范走统一生成方法(多租户约束见关联文档《多租户与数据隔离规范》第 3 章)。
5.7 消息常量规范
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| Topic 命名 | "topic"、"order-topic" | INFRA_MQ_TOPIC_ORDER = "web-order-topic" |
| Tag 命名 | "tag1"、"order" | INFRA_MQ_TAG_ORDER_PAY = "ORDER_PAY"(与业务域对齐) |
| 消费组 | 默认 Group | INFRA_MQ_GROUP_ORDER_PAY = "web-order-pay-consumer" |
| 消息体状态 | 魔法值描述状态 | 走业务状态定义getConstantCode() |
5.8 正则与校验规则常量
校验规则必须具名化,禁止在注解/校验器中写裸正则。
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 正则 | 校验注解中直接写裸正则 | 集中到常量定义,引用常量名 |
5.9 跨模块引用约束
| 场景 | 约束 |
|---|---|
| 全局常量 | 下沉到公共常量包,所有模块依赖 |
| 业务域常量 | 禁止跨模块直接引用对方常量;需共享时下沉到公共常量包,或传递字符串 |
| 错误码 | 严格按 §4.5.1,模块间只传递 code 字符串,禁止引用对方错误码定义 |
5.10 架构审查红线
- ❌ 业务代码中出现裸字符串/数字(除数学运算
0/1及循环索引i) - ❌ 一个常量定义中混杂
PARAM_、BIZ_、INFRA_等不同分类 - ❌ 跨模块引用对方
XxxConstants - ❌ 缓存 Key、消息 Topic 在业务代码中硬编码拼接
- ❌ 含动态段字符串散落手写拼接,未走统一模板与生成方法
- ❌ 业务状态用裸常量而非集中定义
- ✅ 所有缓存 Key 必须包含版本号,如
v1 - ✅ 业务状态一旦发布视为契约,变更需走兼容性评审
6 · 认证与授权规范
本规范定义用户凭证的传输、统一入口鉴权、上下文传递、权限模型及安全约束。支持 OAuth2.0 与 Session-Cookie 两种模式,两种模式均须遵守全局无状态设计原则(见 §1.4)与前后端分离优先原则(见 §1.5)。所有涉及用户认证的系统必须遵守。
6.1 认证模式选择
| 模式 | 适用场景 | 说明 |
|---|---|---|
| OAuth2.0 / Token | 前后端分离、多端(Web/App/小程序)、第三方接入 | 无状态凭证(自包含),前后端分离场景默认优先 |
| Session-Cookie | 传统后端渲染、单体管理后台、仅 Web 浏览器端 | 有状态凭证(依赖服务端会话),但会话状态必须外置到集中式存储(如 Redis),本实例内存禁止存 Session |
选择优先级:
- 前后端分离项目:优先选择 Token / OAuth2.0(见 §1.5.4),Session-Cookie 仅在单体 + 后端渲染 + 仅 Web 端的特定场景下使用。
- 传统后端渲染项目:可选择 Session-Cookie,但需满足 §1.5.4 的全部条件。
与无状态原则的关系:
- "有状态"是指凭证依赖服务端会话状态,而非"本实例内存有状态"。
- Session-Cookie 模式下,会话数据必须存储到集中式存储(如 Redis、数据库),本实例内存禁止存 Session,确保多实例部署时请求可路由到任意实例。
- 两种模式可并存(如对外 API 用 Token,内部管理后台用 Session),但同一系统内禁止混用两种凭证格式做同一链路的认证。
6.2 OAuth2.0 凭证格式与传输契约
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 传输位置 | Cookie 存凭证(易受 CSRF) | HeaderAuthorization: Bearer <token> |
| 凭证内容 | 载荷含敏感字段(密码、手机号) | 只含userId + scope + exp,敏感信息走独立接口 |
| 刷新机制 | 前端主动判断exp 刷新 | 统一入口拦截,返回"凭证即将过期"信号触发前端静默刷新 |
| 多设备登录 | 无限制或全局互踢 | 按client_id(设备类型)+ deviceId(设备标识)隔离,同一设备类型 + 同一设备标识最多 1 个有效凭证 |
说明:
- "设备类型"指 OAuth2.0 的
client_id(如web、ios、android);"设备标识"为deviceId(如浏览器指纹、设备 UUID),由客户端首次登录时生成并携带。- 同一浏览器多标签页属于同一设备标识,必须复用同一凭证(禁止重复申请新凭证);刷新/切页仅用 refresh token 静默续期,不触发互踢。
- 不同设备(同类型不同
deviceId)才允许各持一个凭证;登录流程须携带deviceId,服务端据此区分"多标签页"与"真多设备"。
6.3 Session-Cookie 契约(单体适用)
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| Cookie 属性 | 无HttpOnly、Secure、SameSite | 必须设置HttpOnly、Secure、SameSite=Lax(或 Strict) |
| CSRF 防护 | 仅依赖 Session 无 CSRF Token | 必须配合 CSRF Token(表单头或自定义 Header) |
| Session 存储 | 进程内存存 Session(重启丢失) | 集中式 Session 存储(如 Redis),支持多实例共享 |
| Session 时效 | 永不过期 | 滑动过期 + 绝对过期双限制(如 30min 滑动 + 8h 绝对) |
6.4 统一入口鉴权策略
认证校验在统一入口完成(单体为入口中间件/过滤器,微服务为 API 网关),业务模块不直接对接认证中心:
外部调用方 → 统一入口 → [凭证校验] → 注入 X-User-Id / X-Scope → 业务模块
- 校验失败:统一入口直接返回未认证/凭证过期错误(401),不进入业务模块。
- 校验成功:统一入口剥离
AuthorizationHeader,注入X-User-Id、X-Scope、X-Client-Id。 - 业务模块禁止从
AuthorizationHeader 自行解析凭证,统一从请求上下文取X-User-Id。 - 单体系统:入口中间件校验后,将用户身份写入请求上下文(如 ThreadLocal/请求属性),模块内直接读取,不强制注入 X-User-Id 头;多实例部署时才需透传上下文头。
6.5 上下文传递
请求上下文(用户身份、链路信息)必须在调用链中传递:
| 场景 | 处理方式 |
|---|---|
| 单体 / 模块化单体 | 进程内请求上下文传递(进入模块边界时从上下文取值) |
| 微服务用户请求链路 | 请求上下文取X-User-Id → 调用拦截器 → 注入 X-User-Id |
| 服务内部调用(无用户) | 使用客户端凭证模式获取服务凭证,注入X-Service-Id |
| 禁止 | 裸传Authorization: Bearer <user-token> 到下游(凭证膨胀、权限放大) |
6.6 权限模型(RBAC 最小化)
| 层级 | 说明 | 对应常量前缀 |
|---|---|---|
| Scope | 凭证中的权限范围,如read、write、admin | AUTH_SCOPE_* |
| 资源权限 | 声明式控制(注解/策略),如hasAuthority('ORDER_WRITE') | AUTH_PERM_* |
- 权限点字符串必须走常量:
AUTH_PERM_ORDER_WRITE = "ORDER_WRITE",禁止裸字符串。 - 权限校验失败统一返回
E2-PERM-000(403)。
6.7 凭证存储与安全
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 前端存储 | localStorage 存凭证(XSS 风险) | 按子模式选择:BFF 模式用httpOnly Cookie;纯 SPA + Token 模式用内存(或 Web Worker)存 access + httpOnly Cookie 存 refresh |
| 凭证黑名单 | 登出时删前端凭证即认为失效 | 统一入口维护服务端黑名单,TTL 按凭证剩余有效期 |
| 密钥管理 | 签名密钥硬编码在代码里 | 走配置中心加密存储,支持密钥轮换(kid 标识当前密钥版本) |
6.7.1 前后端分离凭证存储子模式
前后端分离场景下,凭证存储按两种子模式选择:
模式一:BFF 模式(后端代理)
- 统一用
httpOnlyCookie 存 session/token,前端无感知,免疫 XSS 窃取凭证。 - 由 BFF 层(后端)处理 OAuth2.0 交互与凭证刷新,前端不接触凭证。
- 适用于同源部署、对安全要求高的场景。
模式二:纯 SPA + Token 模式(前后端直连)
- access token 存内存(或 Web Worker),refresh token 存
httpOnlyCookie。 - 页面刷新后内存中的 access token 丢失,需用 refresh token 静默换取新 access token。
- 必须配合 PKCE(防授权码拦截)+ 短时效 access token(降低 XSS 影响面)。
- 多标签页登录态同步:同源标签页通过 BroadcastChannel / LocalStorage 事件同步 access token;跨域场景由统一入口会话维持,避免刷新/切页丢失登录态。
| 场景 | BFF 模式 | 纯 SPA + Token 模式 |
|---|---|---|
| 凭证存放 | 全部在 httpOnly Cookie | access 在内存/Web Worker,refresh 在 httpOnly Cookie |
| OAuth2.0 交互 | BFF 层处理 | 前端 + 后端配合(需 PKCE) |
| 刷新机制 | BFF 静默刷新 | 前端持 refresh token 静默换取 |
| 多标签页 | Cookie 天然共享 | 需 BroadcastChannel 同步 |
| 适用场景 | 同源部署、安全要求高 | 跨域 CDN 静态托管、多端直连 |
6.8 错误码衔接(复用 E2 大类)
| code | 场景 | HTTP |
|---|---|---|
E2-AUTH-000 | 未认证/凭证缺失 | 401 |
E2-AUTH-001 | 凭证过期 | 401 |
E2-AUTH-002 | 凭证非法/签名错误 | 401 |
E2-AUTH-003 | 凭证即将过期(触发刷新) | 401 |
E2-AUTH-004 | 单点登录被踢 | 401 |
E2-PERM-000 | 无权限 | 403 |
6.9 常量衔接(复用 AUTH_ 前缀)
AUTH_前缀常量的参考值见 附录 A.3(参考实现)。
6.10 架构审查红线
- ❌ 业务模块直接解析
AuthorizationHeader - ❌ 裸传用户凭证到下游模块/服务
- ❌ 权限点用裸字符串
- ❌ 签名密钥硬编码
- ❌ 凭证黑名单仅删前端不维护服务端
- ✅ 统一入口鉴权,业务模块只认
X-User-Id - ✅ 调用链区分用户链路(
X-User-Id)与服务链路(X-Service-Id)
7 · 远程调用与韧性设计
本规范定义远程调用(外部系统、第三方 API、服务间调用)的超时、重试、熔断、降级策略。系统 80% 的故障来自调用链,必须显式约束。
适用范围说明:
- 单体架构:进程内模块调用无需超时/熔断/重试;但调用外部系统(第三方 API、其他系统、消息中间件等)仍必须遵守本节全部约束。
- 微服务架构:服务间远程调用与外部系统调用均须遵守本节约束。
7.1 超时配置
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 全局超时 | 全局统一5s,不区分读/写 | 连接超时1s,读超时按接口 SLA 分级(P0: 3s,P1: 10s) |
| 配置方式 | 全局配置覆盖所有下游 | 按下游系统/接口隔离配置,禁止全局覆盖 |
7.2 重试策略
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 重试范围 | 默认重试 3 次,不加退避 | 仅幂等接口允许重试,退避策略exponential backoff,最大重试 2 次 |
| 重试标识 | 无标识,盲目重试 | 非幂等接口必须显式标记不可重试,幂等接口默认允许 |
- 幂等接口允许重试:如库存扣减、状态确认类操作。
- 非幂等接口禁止重试:如创建订单、转账类操作。
7.3 限流策略
限流与熔断互补:熔断是"对方出问题我保护自己",限流是"请求太多我主动拒绝"。高并发场景下,统一入口与服务层必须同时配置限流。
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 限流层级 | 只在统一入口限流,服务层无保护 | 统一入口限流 + 服务层限流 + 核心接口独立限流,三层防护 |
| 限流算法 | 固定窗口计数(临界突发流量击穿) | 令牌桶(平滑限流)或漏桶(强制匀速),核心接口用并发数限制 |
| 限流粒度 | 全局限流,无法区分接口/用户 | 按接口 + 用户/租户/客户端 IP 多维限流 |
| 限流响应 | 直接返回 500 | 返回E1-RATE-000(429)+ Retry-After 头,提示重试时间 |
三层限流的配置参考示例见 附录 A.4(参考实现)。
7.4 熔断降级
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 熔断参数 | 全靠框架默认参数 | 按错误率(50%)+ 慢调用比例(80% 响应超 1s)双维度熔断 |
| 降级策略 | 无降级,直接抛异常 | 提供降级策略,返回空集合或缓存数据 |
熔断参数配置参考示例见 附录 A.5(参考实现)。
7.5 架构审查红线
- ❌ 全局超时配置覆盖所有下游系统
- ❌ 非幂等接口允许重试
- ❌ 无降级策略,熔断后裸抛异常
- ✅ 按下游系统隔离超时配置
- ✅ 熔断触发后必须有降级策略
8 · 缓存全生命周期规范
本规范定义缓存的更新策略、一致性防护、Key 命名及 TTL 管理。缓存的更新策略和一致性是生产事故高发区。
8.1 更新模式
| 场景 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 写场景 | 先删缓存再写 DB | Cache Aside:先写 DB,再删缓存 |
| 读场景 | 强制强一致 | 允许短暂不一致,DB 为准 |
| 并发写 | 无锁保护 | 配合分布式锁(多实例部署时)或乐观锁,避免脏写 |
8.2 穿透防护
| 场景 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 缓存穿透 | 只用null 值缓存 | 布隆过滤器 + 空值缓存(TTL2min)双层防护 |
- 缓存未命中且数据不存在时,写入空值缓存(TTL ≤ 2 分钟),防止恶意高频请求打穿到 DB。
8.3 雪崩防护
| 场景 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 热点 Key | 热点 key 永不过期 | 热点 key 设置随机抖动 TTL(基础值 + 0~30s 随机偏移) |
| 批量失效 | 大量 key 同时过期 | 基础 TTL 分散,避免整点失效 |
8.4 本地缓存约束
| 场景 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 混用策略 | 本地缓存与分布式缓存混用无过期同步 | 本地缓存 TTL 必须 ≤ 分布式缓存 TTL 的1/3,且禁用本地缓存做写操作 |
| 一致性 | 本地缓存写后不同步 | 写操作只走分布式缓存,本地缓存仅读 |
| 单实例部署 | 本地缓存可独立使用 | 但需评估进程重启导致的缓存重建压力 |
单实例场景说明:单实例部署且无分布式缓存时,本地缓存 TTL 按业务可接受的数据延迟自行设定,不受 1/3 约束限制;一旦扩展为多实例,必须引入分布式缓存,并遵守"本地缓存 TTL ≤ 分布式缓存 TTL 的 1/3"约束(见 §1.4.2)。
8.5 缓存热更新与重建
缓存预热与热点 Key 变更时的重建策略,避免冷启动与缓存击穿。
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 系统启动 | 无预热,上线即面对全量穿透 | 核心热点数据(如字典、配置、Top 商品)启动时预热 |
| 热点 Key 变更 | 直接删除热点 Key,瞬间击穿 DB | 热点 Key 变更时先重建再替换,或加互斥锁仅允许一个线程重建 |
| 批量失效重建 | 全量 Key 同时失效,DB 被打满 | 批量失效时按批次重建,控制重建并发度,DB 侧限流保护 |
| 缓存击穿 | 缓存过期瞬间大量请求回源 | 热点 Key 用互斥锁/逻辑过期(返回旧值 + 异步更新)防止击穿 |
缓存重建配置参考与热点 Key 重建的具体手段(双 Key 版本号切换、逻辑过期 + 异步重建)见 附录 A.6(参考实现)。
8.6 架构审查红线
- ❌ 先删缓存再写 DB
- ❌ 缓存穿透无防护
- ❌ 热点 Key 固定 TTL 导致雪崩
- ❌ 本地缓存参与写操作
- ✅ Cache Aside 模式:先写 DB,再删缓存
- ✅ 空值缓存 TTL ≤ 2min
- ✅ 热点 Key 加随机抖动
9 · 消息队列消费规范
本规范定义消息消费者的异常处理、幂等设计、批量消费及顺序消息约束。
9.1 消费异常处理
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 异常吞没 | try-catch 后静默吞掉异常 | 异常必须抛出或转入死信队列(DLQ),禁止自动 ACK 后业务失败 |
| ACK 策略 | 自动 ACK | 手动 ACK,业务成功后 ACK,异常时 NACK 进 DLQ |
9.2 幂等设计
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 幂等约定 | 依赖"业务天然幂等"口头约定 | 所有消费者必须实现幂等键(bizId + msgId),幂等表/键保留 7 天 |
- 消费前先尝试写入幂等键:首次写入成功则执行业务;写入失败(已存在)视为重复消费,直接跳过。
9.3 批量消费
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 批量大小 | 为提性能无限加大批量 | 批量大小上限500 条/次,总耗时超 30s 强制拆分 |
9.4 顺序消息
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 全局顺序 | 全局顺序导致单分片热点 | 仅在必要场景(如订单状态机)用分区键顺序,禁止全局顺序 |
- 发送时按业务主键(如 orderId)哈希选择分区,保证同一业务键的消息顺序消费。
9.5 架构审查红线
- ❌ 自动 ACK + 异常静默吞没
- ❌ 无幂等键保护
- ❌ 批量消费无上限
- ❌ 全局顺序消息
- ✅ 手动 ACK,异常进 DLQ
- ✅ 幂等键
bizId + msgId,保留 7 天 - ✅ 顺序消息仅限分区键级别
10 · 数据访问与查询规范
本规范聚焦查询性能门禁,与持久化层规范互补。
10.1 索引命名
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 索引命名 | idx_a_b 语义不明 | idx_<表名简写>_<字段>,如 idx_ord_user_id |
10.2 深分页
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 深分页 | LIMIT 1000000, 20 | 用游标分页(WHERE id > ? LIMIT 20)或搜索引擎承接 |
10.3 慢 SQL 阈值
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 慢 SQL 发现 | 线上出问题再查 | 开发/测试环境集成 SQL 审计工具,单表查询超200ms 即阻断 CI |
10.4 批量插入
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 批量插入 | 循环逐条INSERT | 必须多值批量INSERT ... VALUES (...), (...),单批次 ≤ 1000 条 |
10.5 读写分离与连接复用
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 读写路由 | 所有查询走主库,从库闲置 | 读流量按规则路由到从库(报表、列表、非核心读),写操作与强一致读走主库 |
| 读写一致性 | 从库延迟导致读旧数据未处理 | 关键读(如下单后立即查)强制走主库,或用主库读标记控制一致性 |
| 连接复用 | 每个请求新建连接 | 统一走连接池复用,禁止裸创建数据库连接 |
10.6 事务边界与长事务禁止
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 事务边界 | 事务内嵌套远程调用/文件 IO | 事务只包含数据库操作,远程调用与文件 IO 必须放在事务外 |
| 长事务 | 事务持续时间无限制(如 > 10s) | 事务持续时间默认 ≤ 5s(默认阈值);复杂报表类操作可放宽,但须标注@LongTransaction 并走审批流程,且记录审计日志;非放宽场景长事务必须拆分或改为异步处理 |
| 事务嵌套 | 多层事务嵌套导致锁竞争加剧 | 单层事务为主,嵌套事务必须评估锁粒度 |
说明:
@LongTransaction为代码注释标记(如// @LongTransaction: 审批单号-XXX)或语言特定注解,目的是显式标识长事务以便审计与审批追溯;标注必须关联审批记录,未审批的放宽长事务视为违规(见 §26.12)。
10.7 架构审查红线
- ❌ 索引命名无业务语义
- ❌
LIMIT offset, size深分页 - ❌ 单条循环插入
- ❌ 无索引的
WHERE条件查询上线 - ❌ 微服务架构下跨服务直连对方数据库
- ✅ 游标分页或搜索引擎承接大数据量查询
- ✅ SQL 审计集成,慢 SQL 阻断 CI
- ✅ 批量插入单批次 ≤ 1000
11 · 测试与质量门禁
本规范定义单元测试、集成测试、契约测试的覆盖率阈值及自动化执行约束。
11.1 单元测试
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 测试范围 | 只测接入层 | 核心业务逻辑层覆盖率≥ 70%,分支覆盖 ≥ 60% |
| 测试数据 | 直接连开发环境 DB | 用容器化测试环境(如 Testcontainers)启动数据库/中间件,测试完自动销毁 |
11.2 契约测试
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| API 兼容性 | 口头约定接口字段 | 消费者驱动契约(CDC),API 变更时自动校验兼容性 |
- 契约测试适用于所有对外 API(单体系统的外部接口、微服务系统的服务间接口)。
- 微服务架构下,服务间接口同样必须以契约测试约束,防止隐式破坏。
11.3 性能测试门禁
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 压测范围 | 只压测核心接口,忽视全链路 | 核心链路(登录、下单、支付、查询)必须压测,覆盖读 + 写 |
| 性能指标 | 只看平均延迟 | 必须看 P95/P99 延迟,P95 ≤ 200ms,P99 ≤ 500ms |
| 吞吐量 | 无吞吐量基线 | 核心接口吞吐量基线 ≥ 设计容量的 80%,回归压测不低于基线 |
| 压测环境 | 开发环境压测,数据量与生产不符 | 压测环境数据量必须 ≥ 生产数据量的 30%,索引与配置与生产一致 |
11.4 CI 门禁阈值
| 指标 | 阈值 | 阻断构建 |
|---|---|---|
| 行覆盖率 | ≥ 70% | 是 |
| 分支覆盖率 | ≥ 60% | 是 |
| 单表查询耗时 | ≤ 200ms | 是 |
| 依赖漏洞(高危) | = 0 | 是 |
| 核心接口 P95 延迟 | ≤ 200ms | 是 |
| 核心接口 P99 延迟 | ≤ 500ms | 是 |
| 核心接口吞吐量回归 | 不低于基线 80% | 是 |
11.5 架构审查红线
- ❌ 无单元测试的业务逻辑层代码合并
- ❌ 集成测试直连开发环境 DB
- ❌ API 变更无契约测试
- ✅ 容器化测试环境隔离
- ✅ CI 覆盖率不达标阻断构建
12 · API 设计规范
本规范定义 API 资源命名、HTTP 动词语义、请求/响应结构、版本命名、废弃策略及兼容性约束。
12.1 资源命名
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 资源命名 | 动词式(/getOrder、/createUser) | 名词复数(/orders、/users),子资源用嵌套(/orders/{id}/items) |
| 命名风格 | 大小写混用(/OrderList) | 全小写 + 连字符(/order-items),或下划线(/order_items),全局统一 |
| 资源层级 | 过深嵌套(/a/b/c/d/e) | 最多 3 层嵌套,过深改用查询参数 |
12.2 HTTP 动词语义
| 动词 | 语义 | 幂等性 | 典型场景 |
|---|---|---|---|
| GET | 查询 | 幂等 | 单查、列表、分页 |
| POST | 创建/触发动作 | 非幂等 | 创建资源、触发业务动作(如支付) |
| PUT | 全量更新 | 幂等 | 整体替换资源 |
| PATCH | 部分更新 | 非幂等 | 局部更新资源 |
| DELETE | 删除 | 幂等 | 删除资源 |
- 非幂等操作必须用 POST(或显式标注不可重试),禁止用 GET 做写操作。
- 备注:PATCH 幂等性取决于实现,此处标记为非幂等是出于保守策略;实际设计时若保证请求体语义幂等(如纯字段级覆盖、无条件依赖),可实现幂等 PATCH。
- 查询参数只做过滤/排序/分页,禁止用查询参数做业务动作。
12.3 请求/响应结构
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 分页参数 | 各自定义(pageNum/pageSize、offset/limit 混用) | 全局统一(推荐pageNo/pageSize 或 offset/limit,全局选一种) |
| 排序参数 | 裸字符串拼接(orderBy=name+desc) | 结构化参数(sort=name&order=desc),或 sort=-name(负号表降序),全局统一 |
| 响应结构 | 各接口返回结构不一致 | 统一响应结构(code/message/data),分页数据统一 data.list + data.total |
| 文档 | 无文档或文档与代码不一致 | 文档自动化生成(如 OpenAPI/Swagger),代码与文档同步更新 |
12.4 版本策略
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 版本位置 | URL 路径版本与 Header 版本混用 | 选定一种(推荐 URL Path),全局统一 |
| 废弃 API | 直接删除 | 废弃 API 保留2 个主版本周期,标记 @Deprecated |
URL 路径版本示例见 附录 A.11(参考实现)。
12.5 兼容性约束
- 新增字段:兼容,允许
- 删除字段:不兼容,需发新版本
- 修改字段类型:不兼容,需发新版本
- 枚举值新增:兼容,追加即可
- 枚举值删除/修改 code:不兼容,视为契约变更
12.6 幂等键设计规范
写接口(POST/PATCH)必须支持幂等键(Idempotency-Key),支付、下单、扣款等资金与库存类接口必须使用:
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 幂等键来源 | 客户端不传键或传可预测值 | 客户端为每次写操作生成 UUID,通过Idempotency-Key Header 传递 |
| 服务端处理 | 无幂等校验,重复提交导致重复下单/扣款 | 以幂等键为唯一约束,重复请求返回首次处理结果(幂等键 + 结果缓存) |
| 键存储 | 幂等键仅存内存(重启即丢失) | 幂等键、请求摘要与处理结果存 Redis/DB,TTL 覆盖重试窗口(如 24h) |
| 作用域 | 幂等键全局唯一(不同用户间冲突) | 幂等键按用户维度隔离(userId + Idempotency-Key 联合唯一) |
| 与消息幂等 | 对外幂等键与消息幂等键割裂 | 对外幂等键可复用于下游消息幂等键(见 §9.2),链路统一 |
- 幂等冲突响应:重复请求返回首次处理结果(对外统一 HTTP 200 + 业务 code,如
S0000+ 原结果标识),禁止返回 409 或再次执行业务逻辑——与 §4.6 对外统一入口收敛策略保持一致。 - 幂等键必须由服务端幂等表/分布式锁保障原子性,禁止依赖客户端自觉。
12.7 架构审查红线
- ❌ URL 版本与 Header 版本混用
- ❌ 直接删除已发布 API
- ❌ 修改已发布枚举的 code 值
- ❌ 支付/下单等资金类接口无幂等键保护
- ✅ 废弃 API 保留 2 个主版本周期
- ✅ 破坏性变更必须发新版本
13 · 数据变更管理
本规范定义数据库脚本管理、命名规则及禁止操作,涵盖 DDL(结构)与 DML(数据)两类脚本。
13.1 变更工具
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| DDL 执行 | 手动执行 DDL | 强制使用数据库变更管理工具(如 Flyway、Liquibase、Alembic、goose),脚本纳入版本控制 |
- 单体架构:全库统一变更管线。
- 微服务架构:每服务独立库、独立变更管线。
13.2 脚本命名
13.2.1 基线脚本(Baseline,用于全新环境初始化)
基线脚本按 序号-模块-init-ddl/dml.sql 命名,存放某一基线版本(如 v1.0.0)的完整库结构,用于全新环境快速初始化:
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 命名格式 | init.sql、schema_v2.sql 语义不明 | 序号-模块-init-ddl/dml.sql,如 001-llm-init-ddl.sql |
| 序号 | 序号重复或乱序 | 3 位序号递增(001、002...),全局唯一 |
| 模块 | 无模块标识 | 模块简写(如llm、order),便于定位归属 |
| 基线定位 | 基线 = "永远最新"(需反复修改) | 基线 =某一版本快照(如 v1.0.0),用于全新环境初始化 |
| 基线不可变 | 修改已发布的基线脚本 | 禁止修改已发布基线脚本;更新基线走"重新打基线" |
| 重新打基线 | 无固定节奏 | 定期(如每 major 版本)以 versions/ 全量增量脚本重新生成 init/ 基线 |
13.2.2 DDL / DML 分类
数据库脚本按 DDL(结构)与 DML(数据) 分类存放,禁止混放:
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 分类方式 | DDL 与 DML 混放同一目录/文件 | 独立目录(ddl/、dml/)或独立文件后缀(-ddl.sql、-dml.sql)区分 |
13.2.3 版本脚本管理(增量,另建目录)
日常 DDL 变更只追加版本脚本(增量),与基线脚本分离,另建独立目录存放,命名规范为 V{版本号}-模块-init-ddl/dml.sql:
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 目录分离 | 版本脚本与基线脚本混放 | 另建独立目录(如versions/、migration/)管理增量脚本 |
| 版本命名 | 无版本号、无模块、无类型 | V{版本号}-模块-init-ddl/dml.sql,如 V1.0.0-llm-init-ddl.sql |
| 脚本用途 | 增量脚本用于全新环境初始化 | 增量脚本用于升级/回滚(执行后不可变);全新初始化走基线脚本 |
| 日常变更 | 回头修改基线/已发布脚本 | 日常 DDL 变更只追加版本脚本,禁止修改已发布的基线与版本脚本 |
| 重新打基线 | 无 | 每 major 版本以增量脚本全量生成新基线,替换 init/ |
与变更管理工具的兼容性:基线 + 增量模式与 Flyway/Liquibase 等工具的"脚本不可变"原则兼容——增量脚本执行后不可修改,与工具校验(checksum)机制一致;基线脚本对应工具的 baseline 机制,仅用于全新环境初始化,日常变更一律走增量脚本。
工具原生命名:若使用 Flyway/Liquibase 等工具,脚本命名以工具原生规范为准(如 Flyway 的
V1.0.0__描述.sql、Liquibase 的 changelog),但必须保留版本号-模块-类型的语义信息(可通过 description/changelog 注释体现),确保可追溯。基线脚本、DDL/DML 分类、基线 + 增量目录的示例见 附录 A.12(参考实现)。
13.3 禁止操作
| ❌ 禁止 | 原因 |
|---|---|
DELETE 无 WHERE | 数据误删 |
DROP TABLE 无备份 | 数据丢失 |
ALTER TABLE 大表无在线变更 | 锁表导致服务不可用 |
| 修改已有列的数据类型(缩小) | 数据截断 |
13.4 业务数据生命周期与归档
业务数据(订单、流水、操作记录等)必须有明确的生命周期管理,防止库表无限膨胀:
| 数据层级 | 定义 | 处理方式 |
|---|---|---|
| 热数据 | 高频访问的在线业务数据 | 主库在线存储,索引完整 |
| 温数据 | 访问频率低但仍需在线查询 | 归档到归档表/分库分表/列存,按需精简索引 |
| 冷数据 | 仅审计/合规需要,几乎无在线访问 | 转冷存储(对象存储/数仓),应用侧不直接在线访问 |
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 保留期限 | 业务数据无限期保留在业务表 | 按业务与合规要求定义保留期限(如订单明细在线保留 3 年后转冷存储) |
| 归档方式 | 直接DELETE 永久删除 | 先软删除/归档到归档表,确认无引用后按策略清理;删除需走审批与备份 |
| 清理任务 | 归档清理与业务线程混跑 | 归档/清理走独立定时作业,低峰期执行,分批处理避免长事务与锁表 |
| 合规留存 | 一律删除、无留存 | 涉资金、审计、合规的数据按法定年限留存(如流水保留 ≥ 5 年),留存数据仅冷存储 |
| 与事务表一致 | 业务归档与本地事务表清理混淆 | 本地事务表(见 §21.3)按消息保留期清理;业务数据归档按生命周期策略,两者分离 |
13.5 架构审查红线
- ❌ 手动执行 DDL
- ❌ 基线脚本命名不规范(无序号/模块/类型标识,如
init.sql、schema.sql) - ❌ DDL 与 DML 混放不分类
- ❌ 基线脚本与版本脚本混放同一目录
- ❌ 修改已发布的基线脚本(日常 DDL 变更应追加增量脚本)
- ❌
DELETE/UPDATE无WHERE - ❌ 业务数据无保留期限,无限期堆积
- ✅ 基线脚本按
序号-模块-init-ddl/dml.sql命名,为某一版本快照,可直接用于全新环境初始化 - ✅ 版本脚本另建目录,按
V{版本号}-模块-init-ddl/dml.sql管理,走变更管理工具 - ✅ 大表变更用在线变更工具(如
pt-online-schema-change或gh-ost)
14 · 资源池化配置
本规范定义线程池、连接池的配置公式与命名约束。
14.1 连接池
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 连接池大小 | 凭感觉设置100 | maxPoolSize = (核心数 * 2) + 有效磁盘数,最小 10,最大 50 |
| 超时配置 | 默认30s | connectionTimeout = 3000,idleTimeout = 600000,maxLifetime = 1800000 |
连接池公式的"有效磁盘数"说明与配置参考示例见 附录 A.7(参考实现)。
14.2 线程池
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 线程池命名 | 默认pool-1-thread-1 | 必须自定义命名(biz-pool-%d、async-pool-%d),便于日志追踪 |
| 线程池创建 | 每次新建线程池 | 统一走共享线程池实例(由容器/框架统一管理),配置中心可覆盖 |
| 线程池大小 | 凭感觉设置 | IO 密集型:核心数 * 2;CPU 密集型:核心数 + 1;混合型按比例拆分 |
| 队列容量 | 无界队列(内存溢出)或0(频繁拒绝) | 有界队列,容量 = 预估峰值并发 × 2,且必须配拒绝策略 |
- 拒绝策略建议:任务积压超限时采用"调用方执行"策略,避免静默丢弃。
- 队列容量与线程数需联动:容量越大,允许的积压越多,但响应延迟越高;容量越小,拒绝越快,但可能误拒正常流量。
14.3 架构审查红线
- ❌ 连接池大小凭感觉设置
- ❌ 线程池无自定义命名
- ❌ 业务代码中裸创建线程
- ✅ 连接池按公式配置
- ✅ 线程池命名前缀统一,日志可追踪
15 · 依赖安全与配置安全
本规范定义依赖漏洞扫描、敏感配置管理及加密存储约束。
15.1 依赖安全
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 依赖引入 | 不查漏洞直接引入 | CI 集成 OWASP Dependency-Check,高危漏洞阻断构建 |
15.2 配置安全
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 密码存储 | 明文写在配置文件中 | 敏感配置走配置中心 + 加密存储,本地开发用环境变量注入 |
| 密钥管理 | 硬编码在代码中 | 走配置中心加密存储,支持密钥轮换 |
敏感配置的正反示例与无配置中心的降级方案(环境变量 + 本地加密文件)见 附录 A.8(参考实现)。
15.3 架构审查红线
- ❌ 引入依赖不查漏洞
- ❌ 密码明文写在配置文件中
- ❌ 密钥硬编码
- ✅ CI 集成 OWASP,高危阻断
- ✅ 敏感配置走配置中心加密
16 · 通用编码约束
16.1 时区规范
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 时间存储 | DB 存本地时间 | 全链路 UTC 存储,DTO 层按用户时区转换 |
| 序列化 | 时间类型裸序列化 | 统一时间戳/带时区时间类型,序列化格式yyyy-MM-dd'T'HH:mm:ss'Z' |
UTC 存储与报表统计的取舍方案(查询转换 / 预聚合 /
business_date冗余列)见 附录 A.9(参考实现)。
16.2 业务状态序列化规范
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 序列化 | 业务状态直接序列化枚举名 | 必须显式定义code,序列化 code,且 code 一旦发布不可变更 |
| 反序列化 | 依赖枚举名 | 走自定义反序列化器,按code 映射 |
| 数据库存储 | 直接存枚举本身(枚举名/序列化对象) | 入库映射为code 值存储,读取时按 code 反查枚举 |
16.3 空值处理
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 返回 null | 裸返回null | 统一用Optional 或空集合;DTO 中基本类型必须用包装类 |
| 集合返回 | return null | return Collections.emptyList() |
16.4 并发安全契约
并发场景(线程池、缓存、异步任务、多实例共享资源)必须遵守统一并发契约:
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 共享可变状态 | 共享可变状态无防护,多个线程裸读写 | 优先不可变对象;其次线程封闭(ThreadLocal/栈局部);必须共享时显式加锁并声明锁对象 |
| 锁粒度 | 全局锁/大对象锁导致无谓串行化 | 锁粒度与临界区对齐:读多写少用读写锁;单条数据操作用细粒度锁(如分段锁/分布式锁按业务键) |
| 锁超时 | 锁无超时,持锁线程挂起导致死锁 | 所有锁必须带超时(如 3s 获取超时、5s 持有上限),超时抛业务异常,禁止无限期等待 |
| 锁顺序 | 多把锁加锁顺序不一致(死锁) | 多把锁按固定顺序(如按对象 id 排序)获取;无法排序时用单锁或 tryLock 超时回退 |
| ThreadLocal | 请求线程池复用,ThreadLocal 不清理 | 请求结束时必须清理ThreadLocal(如 finally 中 remove()),防止线程复用导致数据串扰与内存泄漏 |
| 异步上下文 | 异步任务丢失 TraceId/用户上下文 | 异步链路必须显式传递上下文(见 §17.4 链路追踪):提交任务时快照 TraceId/用户身份,异步线程恢复,禁止依赖继承性传递 |
16.5 架构审查红线
- ❌ DB 存本地时间
- ❌ 业务状态序列化枚举名
- ❌ 返回裸
null - ❌ DTO 中使用基本类型
int/long - ❌ 共享可变状态无防护(裸读写)
- ❌ 锁无超时,存在死锁风险
- ❌
ThreadLocal请求结束不清理 - ❌ 异步任务丢失 TraceId/用户上下文
- ✅ 全链路 UTC
- ✅ 业务状态序列化
code,code 不可变更 - ✅ 空集合替代 null,DTO 用包装类
- ✅ 优先不可变对象,共享可变状态显式加锁
17 · 日志规范
本规范定义日志级别、内容格式、敏感信息脱敏、链路追踪及采集约束。日志是生产事故定位的第一依据,缺失或滥用的代价远大于性能损耗。
17.1 日志级别
| 级别 | 使用场景 | 生产开启 |
|---|---|---|
| ERROR | 系统异常、业务失败、基础设施错误 | 是 |
| WARN | 业务异常、预期内异常(如参数校验失败) | 是 |
| INFO | 关键业务节点、请求入口/出口、核心状态变更 | 是 |
| DEBUG | 调试信息、详细参数 | 否(生产环境关闭) |
- 生产环境禁止开启 DEBUG 日志,防止日志爆炸与性能损耗。
- 关键业务节点(下单、支付、库存扣减)必须打 INFO 日志,便于审计与回溯。
17.2 日志内容格式
日志必须包含以下要素,便于检索与关联:
[时间] [级别] [TraceId] [模块] [类名.方法] [用户ID] 消息内容 [关键参数]
- TraceId:一次请求链路唯一标识,跨模块/跨服务传递,禁止缺失。
- 用户ID:涉及用户操作的日志必须携带用户标识;无用户上下文场景(如系统任务、未登录接口)可省略用户 ID,但须以
system或anonymous占位,确保日志格式统一、字段不缺失。 - 关键参数:业务主键(如 orderId、userId)必须输出,禁止只打"操作成功"。
17.3 敏感信息脱敏
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 密码/密钥 | 明文打印密码、密钥、Token | 完全禁止打印,或打印为****** |
| 身份证号/手机号 | 完整打印 | 中间位打码(如138****1234) |
| 银行卡号 | 完整打印 | 只保留后 4 位 |
| 详细堆栈 | 生产环境打印完整堆栈到业务日志 | 堆栈单独输出到错误日志文件,业务日志只打摘要 |
17.4 链路追踪
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| TraceId 生成 | 无 TraceId,无法串联链路 | 统一入口生成 TraceId,全链路传递 |
| TraceId 传递 | 只在本模块传递 | 跨模块/跨服务/跨消息队列传递,异步链路同样携带 |
| TraceId 关联 | 错误日志与正常日志割裂 | 同一 TraceId 的所有日志(正常 + 错误)可关联查询 |
17.5 日志采集与存储
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 单实例部署 | 本地文件即可 | 本地文件 + 日志轮转(按天/按大小),保留 ≥ 30 天 |
| 多实例/微服务 | 各实例本地文件,无法统一查询 | 集中式日志采集(如 ELK、Loki),统一查询与告警 |
| 日志保留 | 保留 < 7 天 | 生产日志保留 ≥ 30 天,错误日志保留 ≥ 90 天 |
17.6 架构审查红线
- ❌ 生产环境开启 DEBUG 日志
- ❌ 日志中明文打印密码/密钥/Token
- ❌ 关键业务节点无 INFO 日志
- ❌ 错误日志无 TraceId,无法定位链路
- ❌ 多实例部署无集中式日志采集
- ✅ 日志必须带 TraceId,全链路可关联
- ✅ 敏感信息必须脱敏
18 · 指标与告警规范
本规范定义 Metrics 指标、SLO 与告警分级约束,与 §17 日志、链路追踪(TraceId)共同构成可观测性三支柱(日志 Logging、指标 Metrics、追踪 Tracing)。没有指标与告警的系统,故障只能在用户投诉后被动发现。
18.1 指标采集(Metrics)
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 指标范围 | 只采集基础设施指标(CPU/内存) | 核心业务接口必须采集 RED 指标:Rate(QPS)、Errors(错误率)、Duration(时延) |
| 时延统计 | 只打平均值 | 必须记录分位数 P50/P95/P99,平均值会掩盖长尾问题 |
| 指标命名 | 无统一命名、标签带实例 IP | 统一命名规范({模块}.{接口}.{指标}),标签禁止携带高基数动态值(如用户 ID) |
| 采集方式 | 业务代码手写打点散落各处 | 统一接入指标 SDK/框架,核心接口自动埋点 |
18.2 SLO 与错误预算
- 核心接口必须定义 SLO(服务等级目标)并量化,如:P99 ≤ 200ms、错误率 ≤ 0.1%。
- 以滚动窗口(如 30 天)计算错误预算(Error Budget = 1 - SLO),预算耗尽须触发发布冻结或加急优化。
- SLO 必须可量化、可验证,禁止"尽快""越早越好"等模糊表述。
18.3 告警分级与响应时效
| 级别 | 定义 | 响应时效(工作日/非工作日一致) | 示例 |
|---|---|---|---|
| P0 | 核心服务不可用、资损、数据损坏 | 立即响应,15 分钟内介入 | 下单接口错误率 > 5%、主库不可用 |
| P1 | 核心功能降级、部分用户受影响 | 30 分钟内介入 | P99 超阈值、缓存大面积失效 |
| P2 | 非核心功能异常,有降级路径 | 4 小时内处理 | 报表任务失败、次要接口抖动 |
| P3 | 低优先级问题 | 下一个工作日处理 | 磁盘水位预警、指标毛刺 |
18.4 告警规则设计
- 告警必须"少而准":禁止无阈值告警(如 CPU 使用率 > 0%)与抖动告警(如单次 P99 毛刺)。
- 告警必须携带服务/实例/TraceId 维度定位信息,可一键跳转排查。
- 告警收敛:同一根因的告警合并,抑制派生告警(如"接口错误率高"抑制其下游"数据库慢"告警)。
- 告警必须有明确恢复条件,防止告警风暴与告警疲劳。
18.5 架构审查红线
- ❌ 核心接口无 P95/P99 指标
- ❌ 关键指标无 SLO,无错误预算机制
- ❌ 核心服务无 P0 告警或告警无人响应
- ❌ 告警无阈值、抖动告警,导致告警风暴
- ✅ RED 指标 + P50/P95/P99 分位数覆盖核心接口
- ✅ 告警分级 + 响应时效 + 收敛抑制
19 · 部署与发布
本规范定义环境划分、配置隔离、发布策略、健康检查及回滚约束。环境管理是架构工程的基础,缺失易导致配置泄露与发布事故。
19.1 环境划分
| 环境 | 用途 | 数据 | 配置 |
|---|---|---|---|
| dev | 开发自测 | 开发数据,可随时重置 | 开发配置 |
| test | 测试验证 | 测试数据,定期同步生产结构 | 测试配置 |
| stage | 预发布 | 与生产同构的数据(脱敏) | 与生产同构的配置(副本) |
| prod | 生产 | 真实数据 | 生产配置(加密存储) |
- 环境之间禁止直连(如 test 直连 prod 数据库),配置必须完全隔离。
- stage 环境必须存在,用于发布前验证,禁止跳过 stage 直接发 prod。
19.2 配置隔离
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 配置文件 | 所有环境配置混在一个文件中 | 按环境拆分配置文件(如application-dev.yml),配置中心按环境隔离 |
| 敏感配置 | 明文写在配置文件中 | 敏感配置走配置中心加密存储,本地开发用环境变量注入 |
| 环境标识 | 无环境标识,配置混用 | 启动时必须显式指定环境(如--spring.profiles.active=prod),禁止默认环境 |
19.3 发布策略
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 单体/简单系统 | 直接全量发布,无回滚预案 | 全量发布 + 回滚预案,发布前备份当前版本 |
| 微服务/核心系统 | 无灰度,直接全量 | 蓝绿发布或灰度发布,先小流量验证,再全量 |
| 发布窗口 | 业务高峰期发布 | 低峰期发布(如凌晨),核心系统禁止白天发布 |
19.4 健康检查
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 健康检查 | 无健康检查,发布即切流 | 必须暴露健康检查接口(如/health),发布时先检查再切流 |
| 检查内容 | 只检查进程存活 | 检查关键依赖(数据库、缓存、消息队列)连通性 |
| 就绪检查 | 启动未完成即接流量 | 就绪检查(readiness)与存活检查(liveness)分离,未就绪不切流 |
19.5 回滚约束
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 回滚预案 | 发布失败无回滚手段 | 发布前必须准备回滚预案,版本号与制品可快速回滚 |
| 数据库变更 | 发布与 DDL 变更无顺序约定 | DDL 必须向后兼容;应用发布与 DDL 执行顺序按变更类型确定(加字段/索引/表:先执行向后兼容的 DDL——可空字段或带默认值,再发布应用;删字段/表/约束:先发布应用——确保新代码不再依赖,再执行 DDL),确保任意时刻回滚到旧版本应用,数据库结构仍能兼容 |
19.6 优雅停机与流量摘除
发布(蓝绿/灰度/滚动)时,旧实例摘除流量后必须优雅停机,禁止直接强杀进程掐断存量请求:
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 流量摘除 | 直接停止实例,存量请求被掐断 | 先从负载均衡摘除实例(下线探针/就绪状态置为不健康),停止接收新流量,再处理存量 |
| 存量请求 | 无等待窗口,立即强杀 | 等待存量请求处理完成,设置等待窗口(如 30s),超时后再强杀 |
| 连接排空 | 进程退出时连接未释放 | 关闭监听端口 → 排空数据库/消息/HTTP 连接池 → 完成优雅停机回调 → 退出 |
| 平滑发布 | 蓝绿/灰度切换瞬间中断 | 新实例就绪检查通过后再摘除旧实例流量,滚动发布每次只摘一个批次 |
19.7 架构审查红线
- ❌ 环境配置混用(如 test 配置连 prod 数据库)
- ❌ 无 stage 环境,直接发 prod
- ❌ 发布无健康检查,启动即切流
- ❌ 发布无回滚预案
- ❌ 发布时直接强杀旧实例,无优雅停机
- ❌ 敏感配置明文存储
- ✅ 环境隔离 + 健康检查 + 回滚预案三要素必须满足
- ✅ 摘除流量 → 等待窗口 → 连接排空 → 优雅退出
20 · 镜像与 CI/CD
本规范定义容器镜像构建、镜像仓库安全、CI/CD 流水线及构建产物管理约束。镜像与 CI/CD 是质量门禁到生产部署的桥梁,所有涉及容器化部署的系统必须遵守。
20.1 镜像构建规范
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 基础镜像 | 使用latest 或漂移版本 | 固定明确版本,优先官方镜像,禁止latest |
| 镜像分层 | 每条指令一层,镜像臃肿 | 合并 RUN 指令,减少层数与体积 |
| 构建上下文 | 包含.git、node_modules 等无用文件 | 构建上下文最小化,.dockerignore 排除无关文件 |
| 构建方式 | 单阶段构建,体积大 | 多阶段构建(编译环境 → 运行环境),仅保留运行产物 |
| 镜像标签 | 仅latest,无法定位版本 | 测试版:分支名-时间戳-构建号;正式版:语义化版本;latest 仅限最新正式版 |
| 不可变性 | 发布后修改已发布镜像 | 镜像不可变,发布后禁止修改,变更走新版本 |
20.1.1 镜像标签命名规范
| 镜像类型 | 标签格式 | 示例 | 说明 |
|---|---|---|---|
| 测试版 | 分支名-时间戳-构建号 | dev-202608061030-123 | 每次构建唯一,可追溯代码分支与构建序号 |
| 正式版 | 语义化版本 | v1.2.3 | 遵循语义化版本规范(主版本.次版本.修订),用于生产发布 |
| 通用 | latest | latest | 仅允许打在最新的正式版镜像上,禁止用于测试版 |
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 分支名 | 大写、含/ | 小写,/ 转 -(如 feature/order → feature-order) |
| 时间戳 | 无时间戳,无法定位构建时间 | YYYYMMDDHHMM 格式 |
| 构建号 | 无构建号,无法定位构建顺序 | 流水线构建序号递增(如123) |
| latest 使用 | 测试版打latest;非最新正式版打 latest | 仅最新正式版打latest |
| 标签分离 | 正式版复用测试版标签 | 正式版与测试版标签严格分离 |
20.2 镜像仓库与安全
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 仓库来源 | 生产环境直拉公共镜像仓库 | 统一私有镜像仓库,公共镜像先拉取到私有仓再使用 |
| 漏洞扫描 | 未扫描直接上线 | CI 集成镜像扫描(如 Trivy、Clair),高危漏洞阻断上线 |
| 镜像完整性 | 无签名校验 | 镜像签名校验(如 cosign),防止篡改 |
| 拉取策略 | 生产按标签拉取,易被覆盖 | 生产固定digest 拉取,保证不可变 |
20.3 CI/CD 流水线规范
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 流水线阶段 | 无固定阶段,随意执行 | 固定阶段:代码检查 → 单元测试 → 构建 → 镜像扫描 → 部署 |
| 环境递进 | 跳级部署(跳过 stage 直接 prod) | 按 dev → test → stage → prod 递进,禁止跳级 |
| 失败门禁 | 门禁不达标仍放行 | 覆盖率/慢 SQL/依赖漏洞不达标阻断流水线 |
| 流水线幂等 | 重跑产生副作用(重复建表、重复发消息) | 流水线可重复执行,无副作用,失败可安全重跑 |
20.4 构建与发布策略
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 产物管理 | 每次构建产物随机,无法追溯 | 构建产物不可变,统一制品仓库版本化管理,可追溯 |
| 部署复用 | 每环境重新构建 | 同一构建产物贯穿环境递进,各环境只做配置差异 |
| 发布方式 | 直接全量替换 | 结合 §19 部署与发布的蓝绿/灰度策略 |
20.5 架构审查红线
- ❌ 基础镜像使用
latest - ❌ 测试版镜像打
latest标签 - ❌ 非最新正式版打
latest标签 - ❌ 测试版镜像标签无分支/时间戳/构建号(无法追溯)
- ❌ 生产环境直拉公共镜像仓库
- ❌ 镜像高危漏洞未扫描通过即上线
- ❌ CI 跳级部署(如跳过 stage 直接 prod)
- ❌ 构建产物不版本化、无法追溯
- ❌ 流水线重跑产生副作用
- ✅ 镜像固定版本 + digest 拉取,扫描通过才上线
- ✅ 流水线环境递进 + 门禁阻断 + 幂等可重跑
21 · 事务规范
本规范定义事务边界、分布式事务策略、本地事务表模式及一致性约束。事务是数据一致性的核心,缺失易导致脏数据与资金损失。
21.1 事务边界
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 事务范围 | 事务内嵌套远程调用/文件 IO/消息发送 | 事务只包含数据库操作,远程调用与文件 IO 必须放在事务外 |
| 事务声明 | 隐式事务,无明确边界 | 显式声明事务边界(注解/代码块),禁止隐式提交 |
| 事务隔离 | 默认隔离级别不评估 | 默认用READ COMMITTED;涉及资金/库存用 REPEATABLE READ 或显式加锁 |
21.2 分布式事务策略
跨服务/跨模块的分布式事务,按业务一致性要求选择策略:
| 策略 | 适用场景 | 一致性 | 说明 |
|---|---|---|---|
| 本地事务 | 单模块内操作 | 强一致 | 单库事务即可 |
| 本地事务表 | 本地事务 + 消息发送 | 最终一致 | 本地事务写业务表 + 消息表,异步投递消息 |
| Saga | 长流程业务(如订单 → 库存 → 支付) | 最终一致 | 每步本地事务 + 补偿动作,失败时按序回滚 |
| TCC | 资金/库存等强一致要求 | 强一致(预留) | Try(预留)→ Confirm(确认)/ Cancel(取消),需业务侵入 |
| 2PC/XA | 跨库强一致(性能差) | 强一致 | 仅限同机房、低并发场景,禁止跨服务使用 |
- 优先选择:本地事务表(简单、可靠、性能好),其次 Saga,TCC 仅在资金/库存等核心场景使用。
- 禁止:跨服务使用 2PC/XA,性能差且易死锁。
21.3 本地事务表模式(推荐)
本地事务 + 消息发送的一致性保障,推荐用于异步解耦场景:
本地事务:
1. 写业务表(如订单表)
2. 写消息表(如 order_msg,状态 = 待发送)
提交事务(业务表与消息表同库,保证原子性)
异步任务:
3. 定时扫描消息表,投递消息到 MQ
4. 投递成功后更新消息表状态 = 已发送
5. 投递失败重试,超限后告警
- 消息表必须包含:消息 ID、业务键、消息体、状态、重试次数、
created_at(创建时间)、cleaned_at(清理时间)。 - 投递失败必须重试,重试超限(如 5 次)后告警并人工介入。
清理策略:
- 已投递成功的消息记录必须定期清理(如保留 7 天后删除或归档),防止消息表长期累积膨胀。
- 清理任务必须走独立定时作业(独立线程池/调度),避免与业务线程竞争资源。
- 清理以
created_at为保留判断依据,清理完成后回写cleaned_at,便于审计与排查。
21.4 架构审查红线
- ❌ 事务内嵌套远程调用/文件 IO
- ❌ 跨服务使用 2PC/XA
- ❌ 本地事务 + 消息发送无本地事务表保障
- ❌ 分布式事务无补偿/回滚策略
- ✅ 事务边界只包含数据库操作
- ✅ 异步解耦优先用本地事务表模式
22 · 文件与对象存储规范
本规范定义文件上传、存储、访问控制与生命周期管理约束(对应错误码
E3-FILE)。头像、附件、导出文件等是 Web 系统的常见需求,缺少约束会导致磁盘膨胀、越权下载与恶意上传。
22.1 存储选型与分类
| 文件类型 | 推荐存储 | 访问方式 |
|---|---|---|
| 头像/图片/富文本附件 | 对象存储(如 MinIO、云 OSS) | 私有读写 + 签名 URL |
| 导出/报表文件 | 对象存储或本地临时目录(短生命周期) | 签名 URL,TTL 到期清理 |
| 日志/备份类大文件 | 对象存储冷存储/归档 | 非在线访问 |
- 禁止把业务文件直接存数据库大字段(
BLOB),大字段导致数据库膨胀与性能劣化。
22.2 上传约束
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 大小限制 | 无限制或仅前端限制 | 后端强制限制上传大小(如图片 ≤ 5MB、附件 ≤ 50MB),超限返回E1-FILE-xxx |
| 类型校验 | 仅信任文件名后缀 | 校验文件内容签名(魔数)+ 后缀白名单,禁止可执行文件(.exe/.sh/.jsp) |
| 临时文件 | 上传失败/过期后残留临时文件 | 临时目录必须定期清理(TTL,如 24h),独立定时作业扫描删除 |
22.3 访问控制
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 私有文件 | URL 公开可访问(猜 URL 即下载) | 对象存储私有读写;对外访问走签名 URL(带过期时间与权限,如有效期 ≤ 10min) |
| 防盗链 | 任意来源可热链引用 | 以签名 URL 参数校验 + Host 白名单为主要防护;Referer 可被伪造/为空,仅作辅助手段,不可作为安全依赖;必要时加 CDN 防盗链 |
| 越权下载 | 任意登录用户可下载他人文件 | 文件归属校验:下载接口必须校验文件属主与访问者权限(水平越权,见 §25.3) |
22.4 分片上传与断点续传
- 大文件(> 50MB)必须支持分片上传:初始化上传任务 → 逐片上传 → 合并校验(MD5/大小)。
- 分片需支持断点续传与失败重试(重试幂等,见 §12.6 幂等键)。
- 合并前校验分片完整性,合并后清理分片与临时任务记录。
22.5 架构审查红线
- ❌ 文件存数据库大字段(
BLOB) - ❌ 上传无大小/类型后端校验
- ❌ 私有文件公开 URL 可下载(无签名)
- ❌ 下载接口不校验文件属主(越权下载)
- ❌ 临时文件不清理
- ✅ 对象存储私有读写 + 签名 URL + 防盗链
- ✅ 大文件分片上传 + 断点续传
23 · 定时任务与分布式调度规范
本规范定义定时任务的分布式调度约束(防重复执行、超时、重试、执行记录)。文档多处依赖定时任务(本地事务表清理 §21.3、缓存预热 §8.5、报表预聚合 §16.1),调度本身必须有规范,否则多实例部署时任务重复执行。
23.1 任务定义
- 每个任务必须有全局唯一标识、模块归属、执行间隔与描述,禁止匿名任务。
- 任务执行必须可观测:开始/结束/失败/耗时写入执行记录(与 §17 日志、§18 指标联动)。
23.2 分布式防重复执行
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| 多实例执行 | 每实例独立执行,任务重复运行 | 分布式环境必须保证单实例执行:选主(如 Quartz 集群/xxl-job 调度中心)或分布式锁(如 Redis 锁 + 租约) |
| 锁时效 | 分布式锁无过期时间,持锁者宕机 | 锁必须带过期时间(租约),过期自动释放,防止持锁实例宕机导致任务永久阻塞 |
| 重叠执行 | 上一轮未结束下一轮已开始 | 禁止任务重叠:任务开始/结束标记或锁的tryLock,超时未拿到锁则跳过本轮 |
23.3 超时与失败重试
- 任务必须配置超时时间,超时中断并告警(P2,见 §18.3),防止任务卡死占用线程。
- 失败重试策略按任务类型定义:允许重试的任务设置次数上限(如 3 次)与退避间隔;禁止无限重试。
- 重试必须幂等(见 §12.6 幂等键、§9.2 消息幂等),重试不产生重复副作用。
23.4 执行记录留存
- 每次执行记录:任务 ID、触发时间、耗时、结果(成功/失败/跳过)、失败原因。
- 执行记录保留期限按审计要求(如 ≥ 90 天),定期归档(见 §13.4 数据生命周期)。
- 连续失败任务必须告警并自动降频或暂停,禁止静默失败。
23.5 架构审查红线
- ❌ 多实例部署任务重复执行(无选主/无锁)
- ❌ 分布式锁无过期时间
- ❌ 任务无超时、无失败重试上限
- ❌ 无执行记录,失败静默
- ✅ 单实例执行保障(选主/分布式锁)+ 锁租约
- ✅ 超时中断 + 幂等重试 + 执行记录留存
24 · 数据库备份与恢复(RTO/RPO)
本规范定义数据库备份节奏、校验与恢复演练约束。事务一致性(§21)与缓存(§8)保证的是运行期正确性,备份恢复是灾难场景的最后防线,缺失即"裸奔"。
24.1 RTO / RPO 目标
- RTO(恢复时间目标):故障后系统恢复可用所需时间,按业务等级定义(如核心库 ≤ 30min,普通库 ≤ 4h)。
- RPO(恢复点目标):可接受的数据丢失量(如核心库 ≤ 5min,即丢失不超过 5 分钟数据)。
- 所有数据库必须声明 RTO/RPO 目标并纳入备份方案设计,禁止无目标"每日备份"。
24.2 备份节奏
| 备份类型 | 频率 | 说明 |
|---|---|---|
| 全量备份 | 每日(低峰) | 核心库每日全量,普通库可按业务频率(如每周全量 + 每日增量) |
| 增量备份 | 频繁 | 按 RPO 要求配置(如每小时/每 5 分钟),缩小恢复点 |
| 日志归档 | 持续 | 事务日志/WAL 持续归档,用于时间点恢复(PITR) |
- 备份文件必须异地/跨可用区保存,防止单机房故障时备份与数据同毁。
- 备份加密存储(传输与落盘),密钥走配置中心(见 §15.2)。
24.3 备份校验
- 每次备份必须自动校验完整性(校验和/抽样恢复),校验失败立即告警(P1),禁止"备份从未被验证过"。
- 备份作业本身必须可观测:开始/结束/大小/耗时记录,失败告警。
24.4 恢复演练
- 必须定期执行恢复演练(如每季度一次核心库演练),验证 RTO/RPO 目标可达。
- 演练在生产副本/隔离环境执行,演练结果记录并评审;连续演练不达标必须调整备份方案。
- 恢复流程文档化(SOP),演练覆盖:全量恢复、增量+日志时间点恢复、备份文件损坏场景。
24.5 架构审查红线
- ❌ 无 RTO/RPO 目标
- ❌ 备份不校验完整性,从未验证可恢复
- ❌ 备份与数据同机房/同可用区
- ❌ 无恢复演练
- ❌ 备份明文存储、密钥硬编码
- ✅ 全量 + 增量 + 日志归档按 RPO 配置
- ✅ 定期恢复演练验证 RTO/RPO
25 · 应用层安全规范
本规范定义应用层(代码层)的安全约束,与 §15 依赖安全/配置安全互补。SQL 注入、XSS、越权是 Web 系统最常被利用的漏洞,必须在架构与编码层统一防护。
25.1 注入防护
| 约束项 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|
| SQL 注入 | 字符串拼接 SQL、${} 直接拼参数 | 强制参数化查询(PreparedStatement/ORM 参数绑定),禁止拼接 SQL |
| 动态排序 | 排序字段/表名由用户输入直接拼接 | 排序字段走白名单映射,禁止直接拼接用户输入 |
| 其他注入 | 命令注入、模板注入、NoSQL 注入 | 禁止把用户输入拼进系统命令/模板;NoSQL 查询同样参数化 |
25.2 XSS 防护
- 输出侧:所有用户输入渲染到页面/日志前必须转义或编码(HTML/JS 上下文),前端框架默认转义不可关闭。
- 存储侧:富文本内容必须走白名单过滤(标签/属性/协议),禁止"先存储后过滤"或完全信任用户 HTML。
- 配合安全头:
Content-Security-Policy、X-Content-Type-Options: nosniff。
25.3 越权防护(水平 / 垂直)
| 越权类型 | 定义 | ❌ 禁止 | ✅ 推荐 |
|---|---|---|---|
| 水平越权 | 访问他人同等级数据 | 业务代码中裸判断userId == ? | 数据归属校验必须走统一鉴权层/数据权限组件,按资源属主(owner_id)统一拦截 |
| 垂直越权 | 低权限调用高权限接口 | 仅前端隐藏按钮,后端不校验 | 后端必须按角色/权限点校验(RBAC,见 §6.6),权限校验不可依赖前端 |
- 强制要求:数据权限校验必须走统一鉴权层(统一入口/权限组件),禁止在业务代码中裸判断越权(散落判断难以审计、易遗漏)。
- 越权检测:核心资源接口纳入安全测试(见 §11 测试),契约测试覆盖权限场景。
25.4 其他应用层风险
- 文件上传安全:见 §22.2(大小/类型/内容校验)。
- SSRF:禁止用户输入直接作为目标 URL 发起服务端请求,目标地址走白名单/内网地址黑名单。
- CSRF:写操作禁止仅靠 Cookie 鉴权,配合 CSRF Token 或自定义 Header(见 §6.3)。
25.5 架构审查红线
- ❌ SQL 字符串拼接、非参数化查询
- ❌ 用户输入未转义直接渲染(XSS)
- ❌ 数据权限在业务代码中裸判断(水平/垂直越权)
- ❌ 用户输入直拼系统命令/目标 URL(命令注入/SSRF)
- ✅ 参数化查询 + 排序白名单
- ✅ 统一鉴权层做数据权限校验,业务代码零散权限判断为零
26 · 架构审查红线(汇总)
本章为正文 §1~§25 各章红线的完整汇总速查,逐条标注来源章节;审查时按本章逐条核对,完整条款见各章末尾红线。红线为强制约束,违反即评审不通过。
26.1 架构层
- ❌ 接入层写业务逻辑、直接操作数据访问层 → §2.2
- ❌ 跨模块/跨服务引用对方错误码、常量定义 → §2.3 / §4.5 / §5.9
- ❌ 模块结构按技术分层平铺(
controller/、service/、dao/平铺) → §2.1 - ❌ 微服务架构下跨服务直连对方数据库 → §2.3
- ❌ 默认将有状态设计作为首选(如本地内存存会话) → §1.4.1
- ❌ 以"实现简单"为由保留状态,未评估副作用 → §1.4.2
- ❌ 有状态设计未显式标注
@Stateful及原因 → §1.4.2 - ❌ 多实例部署仍用本实例内存存状态 → §1.4.2
- ❌ 前后端分离项目仍用后端渲染(如 JSP/Thymeleaf 直出页面) → §1.4.4 / §1.5.5
- ❌ 前后端分离项目用 Session-Cookie 做认证(跨域/多端受限) → §1.4.4 / §1.5.5
- ❌ 后端接口返回 HTML 片段而非 JSON 数据 → §1.4.4 / §1.5.5
- ❌ 模块依赖对方具体实现类(而非接口) → §3.1
- ❌ 业务功能拓展用 if-else 硬编码分支 → §3.3
- ❌ 扩展点无默认实现 / 扩展修改核心模块代码 → §3.3
- ❌ 扩展实例有状态 → §3.3
26.2 错误码与常量
- ❌ 自行对错误码前缀做字符串判断 → §4.3
- ❌ 业务代码中出现裸字符串/数字(除数学
0/1) → §5.1 - ❌ 错误码/业务状态不用枚举定义(散落裸字符串/数字) → §4.4 / §5.4.1
- ❌ 业务状态用散落裸常量而非集中定义 → §5.4
- ❌ 业务状态序列化枚举名 → §16.2
- ❌ 业务状态直接存枚举本身(枚举名/序列化对象入库) → §16.2
- ❌ 模块间传递非统一响应结构 → §4.7
- ❌ 一个常量定义中混杂不同分类前缀(
PARAM_/BIZ_/INFRA_混用) → §5.2 - ❌ 缓存 Key、消息 Topic 在业务代码中硬编码拼接 → §5.6 / §5.7
- ❌ 含动态段字符串散落手写拼接,未走统一模板与生成方法 → §5.5
- ✅ 错误码发布后不可变更语义,新增只能追加 → §4.4
26.3 认证授权
- ❌ 业务模块直接解析
AuthorizationHeader → §6.4 - ❌ 裸传用户凭证到下游模块/服务 → §6.5
- ❌ 签名密钥硬编码 → §15.2
- ❌ 权限点用裸字符串,未走
AUTH_常量 → §6.6 - ❌ 凭证黑名单仅删前端不维护服务端 → §6.7
26.4 远程调用韧性
- ❌ 全局超时覆盖所有下游系统 → §7.1
- ❌ 非幂等接口允许重试 → §7.2
- ❌ 无降级策略 → §7.4
26.5 缓存与数据
- ❌ 先删缓存再写 DB → §8.1
- ❌ 缓存穿透无防护 → §8.2
- ❌ 热点 Key 固定 TTL → §8.3
- ❌ 本地缓存参与写操作 → §8.4
- ❌
LIMIT offset, size深分页 → §10.2 - ❌ 单条循环插入 → §10.4
- ❌ 索引命名无业务语义 → §10.1
- ❌ 无索引的
WHERE条件查询上线 → §10.3
26.6 消息队列
- ❌ 自动 ACK + 异常静默吞没 → §9.1
- ❌ 无幂等键保护 → §9.2
- ❌ 批量消费无上限 → §9.3
- ❌ 全局顺序消息 → §9.4
26.7 测试与质量
- ❌ 无单元测试的业务逻辑层代码合并 → §11.1
- ❌ 集成测试直连开发环境 DB → §11.1
- ❌ API 变更无契约测试 → §11.2
- ❌ 慢 SQL 超 200ms 未阻断 → §10.3 / §11.4
26.8 安全与配置
- ❌ 密码明文写在配置文件中 → §15.2
- ❌ 引入依赖不查漏洞 → §15.1
26.9 日志规范
- ❌ 生产环境开启 DEBUG 日志 → §17.1
- ❌ 日志中明文打印密码/密钥/Token → §17.3
- ❌ 关键业务节点无 INFO 日志 → §17.1
- ❌ 错误日志无 TraceId,无法定位链路 → §17.4
- ❌ 多实例部署无集中式日志采集 → §17.5
26.10 部署与发布
- ❌ 环境配置混用(如 test 配置连 prod 数据库) → §19.1 / §19.2
- ❌ 无 stage 环境,直接发 prod → §19.3
- ❌ 发布无健康检查,启动即切流 → §19.4
- ❌ 发布无回滚预案 → §19.5
- ❌ 发布时直接强杀旧实例,无优雅停机 → §19.6
- ❌ 敏感配置明文存储 → §19.2 / §15.2
26.11 镜像与 CI/CD
- ❌ 基础镜像使用
latest→ §20.1 - ❌ 测试版镜像打
latest标签 → §20.1.1 - ❌ 非最新正式版打
latest标签 → §20.1.1 - ❌ 测试版镜像标签无分支/时间戳/构建号(无法追溯) → §20.1.1
- ❌ 生产环境直拉公共镜像仓库 → §20.2
- ❌ 镜像高危漏洞未扫描通过即上线 → §20.2
- ❌ CI 跳级部署(如跳过 stage 直接 prod) → §20.3
- ❌ 构建产物不版本化、无法追溯 → §20.4
- ❌ 流水线重跑产生副作用 → §20.3
26.12 事务规范
- ❌ 事务内嵌套远程调用/文件 IO → §21.1 / §10.6
- ❌ 跨服务使用 2PC/XA → §21.2
- ❌ 本地事务 + 消息发送无本地事务表保障 → §21.3
- ❌ 分布式事务无补偿/回滚策略 → §21.2
26.13 指标与告警
- ❌ 核心接口无 P95/P99 指标 → §18.1
- ❌ 关键指标无 SLO 与错误预算机制 → §18.2
- ❌ 核心服务无 P0 告警 / 告警无人响应 → §18.3
- ❌ 告警无阈值、抖动告警,导致告警风暴 → §18.4
- ❌ 指标标签携带用户 ID、订单号等高基数动态值(cardinality 爆炸) → §18.1
- ✅ RED 指标 + P50/P95/P99 分位数覆盖核心接口 → §18.1
26.14 API 设计
- ❌ 支付/下单等资金类接口无幂等键保护 → §12.6
- ❌ URL 版本与 Header 版本混用 → §12.4
- ❌ 直接删除已发布 API → §12.4
- ❌ 修改已发布枚举的 code 值 → §12.5
- ✅ 写接口支持
Idempotency-Key,服务端幂等保障 → §12.6
26.15 并发安全
- ❌ 共享可变状态无防护(裸读写) → §16.4
- ❌ 锁无超时,存在死锁风险 → §16.4
- ❌
ThreadLocal请求结束不清理 → §16.4 - ❌ 异步任务丢失 TraceId/用户上下文 → §16.4
- ✅ 优先不可变对象,共享可变状态显式加锁 → §16.4
26.16 文件与对象存储
- ❌ 文件存数据库大字段(
BLOB) → §22.1 - ❌ 上传无大小/类型后端校验 → §22.2
- ❌ 私有文件公开 URL 可下载(无签名) → §22.3
- ❌ 下载接口不校验文件属主(越权下载) → §22.3
- ❌ 临时文件不清理 → §22.2
- ✅ 对象存储私有读写 + 签名 URL + 防盗链 → §22.3
26.17 定时任务与调度
- ❌ 多实例部署任务重复执行(无选主/无锁) → §23.2
- ❌ 分布式锁无过期时间 → §23.2
- ❌ 任务无超时、无失败重试上限 → §23.3
- ❌ 无执行记录,失败静默 → §23.4
- ✅ 单实例执行保障 + 锁租约 → §23.2
26.18 数据库备份与恢复
- ❌ 无 RTO/RPO 目标 → §24.1
- ❌ 备份不校验完整性,从未验证可恢复 → §24.3
- ❌ 备份与数据同机房/同可用区 → §24.2
- ❌ 无恢复演练 → §24.4
- ✅ 全量 + 增量 + 日志归档按 RPO 配置 → §24.2
26.19 应用层安全
- ❌ SQL 字符串拼接、非参数化查询 → §25.1
- ❌ 用户输入未转义直接渲染(XSS) → §25.2
- ❌ 数据权限在业务代码中裸判断(水平/垂直越权) → §25.3
- ❌ 用户输入直拼系统命令/目标 URL(命令注入/SSRF) → §25.4
- ✅ 参数化查询 + 统一鉴权层做数据权限校验 → §25.1 / §25.3
26.20 通用编码约束
- ❌ DB 存本地时间 → §16.1
- ❌ 返回裸
null→ §16.3 - ❌ DTO 中使用基本类型
int/long→ §16.3 - ✅ 全链路 UTC 存储,DTO 层按用户时区转换 → §16.1
- ✅ 空集合替代 null,DTO 用包装类 → §16.3
26.21 资源池化
- ❌ 连接池大小凭感觉设置 → §14.1
- ❌ 线程池无自定义命名 → §14.2
- ❌ 业务代码中裸创建线程 → §14.2
- ✅ 连接池按公式配置,超时显式设定 → §14.1
- ✅ 线程池命名前缀统一,日志可追踪 → §14.2
26.22 数据变更管理
- ❌ 手动执行 DDL → §13.1
- ❌ 基线脚本命名不规范(无序号/模块/类型标识) → §13.2.1
- ❌ DDL 与 DML 混放不分类 → §13.2.2
- ❌ 基线脚本与版本脚本混放同一目录 → §13.2.3
- ❌ 修改已发布的基线/版本脚本(日常变更应追加增量脚本) → §13.2.1 / §13.2.3
- ❌
DELETE/UPDATE无WHERE→ §13.3 - ❌ 业务数据无保留期限,无限期堆积 → §13.4
- ✅ 大表变更用在线变更工具(如
pt-osc/gh-ost) → §13.2
附录 A · 参考实现(配置示例、公式与取舍讨论)
本附录收录正文各章的参考实现内容(配置示例、公式说明、实现示例、取舍讨论),供落地时参考;与正文条款冲突时,以正文为准。正文各章节对应的参考条目索引:
| 附录条目 | 对应正文 | 内容 |
|---|---|---|
| A.1 架构模式取舍 | §1.5.2 | 前后端分离 vs 传统后端渲染对比 |
| A.2 统一入口收敛配置示例 | §4.6.2 | 统一入口错误码收敛配置 |
| A.3 认证常量配置示例 | §6.9 | AUTH_ 前缀常量参考值 |
| A.4 限流配置参考 | §7.3 | 三层限流配置示例 |
| A.5 熔断配置参考 | §7.4 | 熔断参数配置示例 |
| A.6 缓存重建配置与实现参考 | §8.5 | 缓存重建配置 + 双 Key/逻辑过期伪代码 |
| A.7 连接池公式与配置参考 | §14.1 | 连接池公式说明与配置示例 |
| A.8 配置安全示例与无配置中心降级 | §15.2 | 敏感配置示例 + 降级方案 |
| A.9 时区与报表统计取舍 | §16.1 | UTC 与报表统计取舍方案 |
| A.10 字符串拼接实现示例 | §5.5 | 占位符模板正反示例 |
| A.11 版本策略示例 | §12.4 | URL 路径版本示例 |
| A.12 数据库脚本目录结构示例 | §13.2 | init/、versions/ 目录示例 |
A.1 架构模式取舍(对应 §1.5.2)
| 架构模式 | 适用场景 | 认证模式 | 优先级 |
|---|---|---|---|
| 前后端分离 | 现代 Web 应用、多端(Web/App/小程序) | Token / OAuth2.0(优先) | 默认优先 |
| 传统后端渲染 | 单体管理后台、简单内部系统 | Session-Cookie | 仅限特定场景 |
A.2 统一入口收敛配置示例(对应 §4.6.2)
# 统一入口配置参考值(微服务为网关,单体为入口中间件)
entry:
error-code:
enabled: true
hide-categories: [E3, E5] # 收敛隐藏的大类
pass-categories: [E1, E2, E4] # 透传的大类
fallback-code: E5-SYS-000 # 收敛后的通用码
fallback-message: "系统繁忙,请稍后重试"
response-status: 200 # 统一入口响应状态码
A.3 认证常量配置示例(对应 §6.9)
AUTH_TOKEN_ACCESS_TTL_MINUTES = 15 # 访问凭证有效期
AUTH_TOKEN_REFRESH_TTL_DAYS = 7 # 刷新凭证有效期
AUTH_TOKEN_BLACKLIST_PREFIX = "auth:bl:" # 黑名单 Key 前缀
AUTH_SCOPE_READ = "read"
AUTH_SCOPE_WRITE = "write"
AUTH_HEADER_USER_ID = "X-User-Id"
AUTH_HEADER_SCOPE = "X-Scope"
AUTH_HEADER_CLIENT_ID = "X-Client-Id"
AUTH_HEADER_SERVICE_ID = "X-Service-Id"
A.4 限流配置参考(对应 §7.3)
# 限流配置参考值(统一入口)
rate-limit:
enabled: true
default-qps: 1000 # 全局默认 QPS
per-interface:
"/v1/orders":
qps: 200 # 核心下单接口独立限流
burst: 50 # 允许突发 50
per-user:
qps: 10 # 单用户 QPS
reject-code: E1-RATE-000
A.5 熔断配置参考(对应 §7.4)
# 熔断配置参考值(通用字段名,具体实现按所用框架映射)
circuit-breaker:
failure-rate-threshold: 50 # 错误率阈值(%)
slow-call-rate-threshold: 80 # 慢调用比例阈值(%)
slow-call-duration-threshold: 1s # 慢调用判定阈值
wait-duration-in-open-state: 30s # 熔断开启后等待时间
permitted-calls-in-half-open-state: 5 # 半开状态允许试探调用数
A.6 缓存重建配置与实现参考(对应 §8.5)
# 缓存重建配置参考值
cache-rebuild:
warmup-on-startup: true # 启动时预热
warmup-keys: [dict, config, top-products]
rebuild-concurrency: 10 # 重建并发度上限
mutex-lock-timeout: 5s # 热点 Key 重建互斥锁超时
手段一:双 Key 版本号切换(重建完成后再原子替换)
# 伪代码(步骤"写新版本数据 + 切换版本引用"必须用 Lua 脚本原子执行)
# KEYS[1] = 版本号 Key;KEYS[2] = 数据 Key 前缀;ARGV[1] = 新数据;ARGV[2] = TTL
def rebuild_hot_key_atomic(biz_key, new_data, ttl):
version_key = f"{biz_key}:ver"
new_version = redis.eval("""
local ver = tonumber(redis.call('GET', KEYS[1]) or '0') + 1
redis.call('SET', KEYS[2] .. ':' .. ver, ARGV[1], 'EX', ARGV[2]) # 写新版本数据
redis.call('SET', KEYS[1], ver) # 原子切换版本引用
return ver
""", 2, version_key, biz_key, new_data, ttl)
# 清理旧版本 Key(非关键路径,可异步执行)
redis.delete(f"{biz_key}:{new_version - 1}")
竞态说明:写新版本数据与切换版本引用必须原子执行(Lua 脚本/事务)。否则并发重建时可能出现:线程 A 写入 version=3 的数据,线程 B 写入 version=2 的数据,线程 B 后执行版本切换将版本号设为 2,导致"数据是 version=3 的、版本号却指向 2"的不一致。
手段二:逻辑过期 + 异步重建(读多写少的超热点)
# 读路径:命中缓存但逻辑已过期 → 先返回旧值,再异步重建
def read(key, expire_at):
data = redis.get(key)
if expire_at - now > 0: # 未逻辑过期,直接返回
return data
if redis.setnx(key + ":lock", 1, ttl=5s): # 仅一个线程触发重建,其余直接返回旧值
submit_async(lambda: rebuild(key))
return data # 返回旧值,避免瞬间击穿 DB
约束:双 Key 切换须保证新数据已完整写入缓存后再切换引用;异步重建任务须走独立线程池,禁止占用业务线程。
A.7 连接池公式与配置参考(对应 §14.1)
# 连接池配置参考值(8 核机器示例)
maximum-pool-size: 20 # (8 * 2) + 4 = 20
minimum-idle: 10
connection-timeout: 3000
idle-timeout: 600000
max-lifetime: 1800000
"有效磁盘数"说明:该公式源自数据库连接池社区经验公式
(core_count * 2) + effective_spindle_count,"有效磁盘数"指并发 I/O 能力的等效主轴数(effective spindle count),并非简单的物理磁盘数量:
- 机械硬盘 / HDD RAID 阵列:≈ 参与数据读写的物理数据盘数量(如 RAID10 的 4 块数据盘 = 4)。
- SSD / NVMe:无寻道延迟,等效主轴数按
1计(或按厂商 IOPS 指标折算)。- 云数据库 / SAN 共享存储:按
1计或按分配的 IOPS 折算。该公式仅为估算起点,最终连接池大小须以压测结果为准。
A.8 配置安全示例与无配置中心降级方案(对应 §15.2)
# ❌ 禁止
password: 123456
# ✅ 推荐
password: ${DB_PASSWORD} # 环境变量或配置中心加密注入
无配置中心的降级方案:本规范多处依赖配置中心,但不强制所有项目部署配置中心。单体小项目可降级为 环境变量 + 本地加密文件 兜底:
- 应用代码只依赖统一配置抽象接口(按需读取配置中心或本地配置源),后续引入配置中心时无需改动业务代码。
- 敏感配置优先环境变量注入;需落盘时使用本地加密文件(文件权限最小化),禁止明文配置文件与硬编码。
- 本地兜底配置仅限无多实例扩展诉求的单体场景;一旦多实例部署或需动态变更配置,必须引入配置中心。
A.9 时区与报表统计取舍(对应 §16.1)
存储层统一 UTC 是底线——时区会随夏令时、服务器迁移、跨区域部署变化,存本地时间会导致数据不可比、不可迁移。按本地时间做报表统计的需求,在查询/聚合层解决,不改存储层:
- 查询转换:报表 SQL 用数据库时区函数转换后再分组,如
created_at AT TIME ZONE 'Asia/Shanghai'。 - 预聚合:高频报表可建按业务时区预聚合的汇总表/物化视图(ETL 时转换),避免大表实时转换。
- 冗余列:确需频繁按业务日期过滤时,可增加
business_date(DATE类型,业务时区的日期,不含时分秒)冗余列,主列仍存 UTC。- 该列仅用于日期维度过滤与分组,不用于精确时间排序或跨时区计算。
- 由应用层/ETL 在写入时从 UTC 主列转换生成,禁止由上游直接传入本地时间。
- 跨天边界场景(如 UTC 23:00 对应次日业务时区)须在转换逻辑中显式处理。
A.10 字符串拼接实现示例(对应 §5.5)
✅ 推荐:占位符模板 + 统一生成方法
INFRA_CACHE_ORDER_DETAIL = "web:order:v1:detail:{id}"
key = KeyBuilder.build(INFRA_CACHE_ORDER_DETAIL, orderId) # → web:order:v1:detail:1001
❌ 禁止:业务代码散落 + 拼接
String key = "web:order:v1:detail:" + orderId
A.11 版本策略示例(对应 §12.4)
✅ URL Path 版本
/v1/orders → 旧版本
/v2/orders → 新版本
A.12 数据库脚本目录结构示例(对应 §13.2)
# 基线脚本命名(§13.2.1)
001-llm-init-ddl.sql # LLM 模块建表脚本(基线 v1.0.0)
002-order-init-ddl.sql # 订单模块建表脚本(基线 v1.0.0)
001-llm-init-dml.sql # LLM 模块初始化数据脚本
# DDL / DML 分类(§13.2.2)
db/
├── ddl/ # 表结构类脚本(建表、加列、索引)
│ ├── 001-llm-init-ddl.sql
│ └── 002-order-init-ddl.sql
└── dml/ # 数据类脚本(初始化数据、字典、配置)
├── 001-llm-init-dml.sql
└── 002-order-init-dml.sql
# 基线 + 增量目录(§13.2.3)
db/
├── init/ # 基线脚本(某一版本快照,全新初始化用)
│ ├── ddl/001-llm-init-ddl.sql
│ └── dml/001-llm-init-dml.sql
└── versions/ # 增量脚本(另建目录,走变更管理工具,如 Flyway/Liquibase)
├── V1.0.0-llm-init-ddl.sql
├── V1.1.0-order-add-index-ddl.sql
└── V1.2.0-order-add-column-ddl.sql
关联文档
本规范为 Web 后端架构规范族的顶层文档。特定领域或特定场景的规范以独立文档形式存在,作为本规范的下位扩展。下位规范不得与本规范冲突,本规范更新时须同步评估下位规范的兼容性。
| 规范名称 | 适用范围 | 触发条件 | 状态 |
|---|---|---|---|
| 《多租户与数据隔离规范》 | SaaS / 多租户产品 | 系统需支持多租户、租户间数据隔离时 | 已发布 |
| 《AI 与大模型扩展规范》 | 集成大模型能力的系统 | 系统需调用第三方模型或自建模型服务时 | 待编写 |
| 《灰度发布实施细则》 | 微服务 / 核心系统 | 需要按比例灰度、分批放量发布时 | 待编写 |
| 《分布式调度规范》 | 多实例 / 分布式部署 | 系统存在定时任务且需防重复执行时 | 待编写 |
说明:多租户规范已有独立文档(
web系统后端通用架构规范-多租户扩展-v1.0.md);《分布式调度规范》与正文 §23 定时任务与分布式调度规范的强制条款互补,如需要更细的调度平台实施细则,可另立下位文档。
引用约定:
- 本规范正文中以"见《XX 规范》"标注的条款,为下位规范的强制引用入口。
- 下位规范须在文档开头声明其上位依据,并注明与本规范的冲突处理原则(以上位规范为准)。
- 下位规范涉及本规范已有概念(错误码、TraceId、环境划分等)时,术语与编号必须保持一致。