- 完成REQ-010-17(性能优化和限流处理)的所有6个阶段 - 创建ADR文档:0026-performance-optimization.md - 创建Prompt文档:027-performance-optimization.md - 创建会话记录:20260119-performance-optimization.md - 创建变更记录:20260119-performance-optimization.md - 创建复盘报告:20260119-performance-optimization-retro.md - 更新index.md和CHANGELOG.md - 完成REQ-010-2(基础实体类和Mapper创建)的前3个阶段 - 更新ADR文档:0011-entity-mapper-create.md - 创建Prompt文档:002-entity-mapper-create.md - 更新index.md 所有文档均按照SSOT方法论创建,包括需求定义、架构决策、提示词资产化、执行会话、变更记录和闭环复盘。
13 KiB
架构决策记录 - 文件存储和解压处理
背景
在 REQ-010-6(元数据拉取核心功能)中,我们已经实现了从 Salesforce Metadata API 拉取元数据的功能。拉取的元数据以 Zip 文件形式返回,需要对这些 Zip 文件进行存储和解压处理。
本需求面临的主要问题包括:
- Zip 文件存储需要支持本地文件系统和 OSS 存储两种方式
- 需要处理大文件(可能达到数百 MB),避免内存溢出
- 文件路径管理需要防止路径遍历攻击
- 存储空间需要监控和告警机制
- 需要自动清理过期文件以释放存储空间
相关约束条件:
- 必须基于现有的 Spring Boot 3 + Vue 3 技术栈
- 必须在 datai-salesforce-metadata 模块下实现
- 必须支持大文件处理,内存使用合理
- 必须验证路径安全性,防止路径遍历攻击
决策
1. 文件存储方案
决策: 使用策略模式实现本地文件系统和 OSS 存储的统一接口,通过配置文件动态切换存储方式。
理由:
- 策略模式符合开闭原则,易于扩展新的存储方式
- 统一接口简化了业务代码,降低耦合度
- 配置文件动态切换支持不同环境的灵活部署
- 本地文件系统适合开发环境,OSS 适合生产环境
实现方案:
- 定义
IFileStorageService接口,包含存储、读取、删除等方法 - 实现
LocalStorageService和OssStorageService两个策略类 - 使用 Spring 的
@ConditionalOnProperty注解根据配置自动选择实现类 - 配置项:
file.storage.type(local/oss)
2. 文件解压方案
决策: 使用 ZipInputStream 实现流式解压,避免一次性加载整个 Zip 文件到内存。
理由:
ZipInputStream支持流式处理,内存占用可控- 可以边读取边解压,适合处理大文件
- Java 标准库,无需额外依赖
- 性能稳定,经过充分验证
实现方案:
- 使用
ZipInputStream逐条读取 ZipEntry - 使用
BufferedOutputStream写入解压后的文件 - 支持进度回调,实时报告解压进度
- 支持取消操作,通过标志位中断解压过程
3. 文件路径管理方案
决策: 使用 Java NIO 的 Path API 处理路径,配合正则表达式验证路径安全性。
理由:
PathAPI 提供了跨平台的路径处理能力normalize()方法可以规范化路径,消除.和..startsWith()方法可以验证路径是否在允许的目录下- 正则表达式可以进一步限制文件名和路径格式
实现方案:
- 定义
PathValidator工具类,提供路径验证方法 - 使用
path.normalize().startsWith(basePath)验证路径 - 使用正则表达式限制文件名(不允许包含特殊字符)
- 拒绝包含
..的路径,防止路径遍历攻击
4. 存储空间管理方案
决策: 使用定时任务定期检查存储空间,当空间不足时发送告警通知。
理由:
- 定时任务实现简单,无需额外依赖
- 可以灵活配置检查频率和告警阈值
- 告警通知可以集成现有的通知机制
- 支持多种告警方式(邮件、短信、钉钉等)
实现方案:
- 使用 Spring 的
@Scheduled注解实现定时任务 - 使用
FileStore.getUsableSpace()获取可用空间 - 配置项:
file.storage.warning-threshold(告警阈值,如 80%) - 告警通知使用现有的
INotificationService接口
5. 文件清理方案
决策: 使用定时任务定期清理过期文件,支持配置清理策略。
理由:
- 定时任务实现简单,易于维护
- 可以灵活配置清理策略(保留天数、文件大小等)
- 清理日志记录完整,便于审计
- 支持手动清理和自动清理两种方式
实现方案:
- 使用 Spring 的
@Scheduled注解实现定时任务 - 配置项:
file.cleanup.retention-days(保留天数) - 清理策略:根据文件最后修改时间判断是否过期
- 清理前记录日志,清理后更新统计信息
- 提供 RESTful API 接口支持手动清理
备选方案
1. 文件存储方案备选
备选方案 A: 使用 Spring 的 Resource 抽象,通过 ResourceLoader 动态加载不同的存储实现。
优点:
- Spring 原生支持,无需额外代码
- 支持多种资源类型(classpath、file、http、ftp 等)
缺点:
- 不支持 OSS 存储
- 接口不够灵活,难以扩展
- 不符合本项目需求
备选方案 B: 使用 Apache Commons VFS 实现虚拟文件系统。
优点:
- 支持多种文件系统(local、ftp、sftp、s3 等)
- 统一的接口,易于使用
缺点:
- 引入额外依赖,增加项目复杂度
- 性能不如直接实现
- 过于重量级,不符合本项目需求
2. 文件解压方案备选
备选方案 A: 使用 Apache Commons Compress 库。
优点:
- 支持多种压缩格式(zip、tar、gzip 等)
- 功能丰富,API 友好
缺点:
- 引入额外依赖
- 对于简单的 Zip 解压,Java 标准库已经足够
- 增加项目复杂度
备选方案 B: 先将 Zip 文件完整加载到内存,再解压。
优点:
- 实现简单
缺点:
- 内存占用高,不适合大文件
- 可能导致内存溢出
- 不符合性能要求
3. 文件路径管理方案备选
备选方案 A: 使用字符串操作处理路径。
优点:
- 实现简单
缺点:
- 容易出错,跨平台兼容性差
- 需要手动处理路径分隔符
- 安全性难以保证
备选方案 B: 使用第三方路径验证库。
优点:
- 功能丰富,安全性高
缺点:
- 引入额外依赖
- 增加项目复杂度
- Java NIO 的 Path API 已经足够
4. 存储空间管理方案备选
备选方案 A: 使用第三方监控工具(如 Prometheus + Grafana)。
优点:
- 功能强大,可视化效果好
- 支持多种告警方式
缺点:
- 引入额外依赖,增加运维复杂度
- 部署成本高
- 对于简单的存储空间监控,过于重量级
备选方案 B: 使用操作系统级别的监控(如 cron + shell 脚本)。
优点:
- 不依赖应用层
缺点:
- 与应用解耦,难以集成
- 维护成本高
- 不符合项目架构
5. 文件清理方案备选
备选方案 A: 使用操作系统的定时任务(如 cron)。
优点:
- 不依赖应用层
缺点:
- 与应用解耦,难以集成
- 维护成本高
- 不符合项目架构
备选方案 B: 使用文件系统的自动清理机制(如 tmpwatch)。
优点:
- 系统级支持,性能好
缺点:
- 与应用解耦,难以集成
- 配置不够灵活
- 不符合项目架构
影响
系统架构影响
- 新增模块: 在
datai-salesforce-metadata模块下新增file包,包含文件存储、解压、路径管理等功能 - 接口定义: 定义
IFileStorageService接口,提供统一的文件存储抽象 - 策略模式: 使用策略模式实现不同的存储策略,提高系统扩展性
- 定时任务: 新增两个定时任务(存储空间监控、文件清理),需要配置定时任务执行器
开发流程影响
- 开发工作量: 需要开发 5 个主要功能模块,预计工作量 3-5 人天
- 测试工作量: 需要进行单元测试、集成测试和性能测试,预计工作量 2-3 人天
- 代码规范: 需要遵循项目现有的代码规范和设计模式
- 文档维护: 需要更新接口文档和 API 文档
运维管理影响
- 配置管理: 需要新增配置项(存储类型、告警阈值、保留天数等)
- 监控告警: 需要配置存储空间监控和告警通知
- 日志管理: 需要记录文件操作日志和清理日志
- 存储管理: 需要定期检查存储空间使用情况
风险
技术风险
-
大文件处理风险: 大文件处理不当可能导致内存溢出
- 缓解措施: 使用流式处理,限制内存占用
- 监控指标: 监控 JVM 内存使用情况
-
路径安全风险: 路径验证不完善可能导致路径遍历攻击
- 缓解措施: 使用 Path API 和正则表达式双重验证
- 监控指标: 记录所有文件操作日志
-
OSS 存储风险: OSS 存储不稳定可能导致文件存储失败
- 缓解措施: 实现重试机制和降级策略
- 监控指标: 监控 OSS 存储成功率和响应时间
业务风险
-
存储空间风险: 存储空间不足可能导致文件存储失败
- 缓解措施: 实现存储空间监控和告警机制
- 监控指标: 监控存储空间使用率
-
文件清理风险: 文件清理策略不当可能导致重要文件被删除
- 缓解措施: 清理前记录日志,支持文件恢复
- 监控指标: 记录清理操作日志
实施风险
-
性能风险: 文件解压和清理可能影响系统性能
- 缓解措施: 使用异步处理,限制并发数
- 监控指标: 监控系统 CPU 和内存使用情况
-
兼容性风险: 不同操作系统的路径处理可能存在兼容性问题
- 缓解措施: 使用 Java NIO 的 Path API,保证跨平台兼容性
- 监控指标: 在不同操作系统上进行测试
回滚策略
1. 文件存储回滚策略
如果 OSS 存储出现问题,可以立即切换回本地文件系统:
- 修改配置文件
file.storage.type=local - 重启应用
- 将已存储到 OSS 的文件复制到本地文件系统
2. 文件解压回滚策略
如果流式解压出现问题,可以临时使用完整加载方式:
- 修改代码,使用
ZipFile替代ZipInputStream - 限制文件大小,避免内存溢出
- 优化后重新切换回流式解压
3. 文件清理回滚策略
如果文件清理出现问题,可以立即停止清理任务:
- 修改配置文件,禁用定时任务
- 恢复被误删的文件(如果有备份)
- 修复清理策略后重新启用
4. 整体回滚策略
如果整个功能出现问题,可以回滚到 REQ-010-6 的状态:
- 停止使用文件存储和解压功能
- 将 Zip 文件临时存储在内存中
- 修复问题后重新启用
验收标准
功能验收标准
-
Zip 文件存储
- 本地文件系统存储成功
- OSS 存储成功
- 存储路径正确
- 文件完整性验证通过
- 支持配置动态切换
-
文件解压
- 文件解压成功
- 支持大文件处理(> 100MB)
- 支持流式解压
- 内存使用合理(< 512MB)
- 解压文件结构正确
- 支持进度回调
- 支持取消操作
-
文件路径管理
- 文件路径管理正常工作
- 支持路径规范化
- 支持路径验证
- 路径格式正确
- 路径安全性验证通过
- 防止路径遍历攻击
-
存储空间管理
- 存储空间管理正常工作
- 支持存储空间监控
- 支持存储空间告警
- 存储空间信息准确
- 告警通知及时
-
文件清理
- 文件清理功能正常工作
- 支持过期文件自动清理
- 支持手动清理
- 清理策略可配置
- 清理日志记录完整
性能验收标准
-
文件存储性能
- 本地文件系统存储速度 > 50MB/s
- OSS 存储速度 > 20MB/s
- 并发存储 10 个文件无性能下降
-
文件解压性能
- 解压速度 > 30MB/s
- 内存使用 < 512MB
- 并发解压 5 个文件无性能下降
-
存储空间监控性能
- 监控任务执行时间 < 1s
- 不影响系统正常运行
-
文件清理性能
- 清理任务执行时间 < 5s
- 不影响系统正常运行
安全性验收标准
-
路径安全
- 防止路径遍历攻击
- 防止文件名注入攻击
- 防止符号链接攻击
-
存储安全
- 文件存储权限正确
- OSS 存储访问权限正确
- 文件完整性验证通过
代码质量验收标准
-
代码规范
- 代码符合项目编码规范
- 有清晰的注释
- 通过代码审查
-
测试覆盖
- 单元测试覆盖率 > 80%
- 集成测试覆盖主要场景
- 性能测试通过
-
文档完整
- 接口文档完整
- API 文档完整
- 使用文档完整
视觉锚点
Visual Reference
引用 Canvas 的具体节点或快照:
- Authentication.canvas - 项目架构视觉化展示
- 具体节点: 集成核心 - 提供与Salesforce的各种连接方式
Status
- Draft
- Accepted
- Superceded
参考资料
列出与该决策相关的参考资料,包括文档、文章或其他资源:
- REQ-010-7.md - 文件存储和解压处理需求文档
- REQ-010-6.md - 元数据拉取核心功能需求文档
- file/index.md - 文件模块 API 文档索引
- Java NIO Path API 文档: https://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html
- Spring Boot 文件上传文档: https://docs.spring.io/spring-boot/docs/current/reference/html/web.html#web.servlet.spring-multipart
- Apache Commons Compress 文档: https://commons.apache.org/proper/commons-compress/