423 lines
13 KiB
Markdown
423 lines
13 KiB
Markdown
# 架构决策记录 - 文件存储和解压处理
|
||
|
||
## 背景
|
||
|
||
在 REQ-010-6(元数据拉取核心功能)中,我们已经实现了从 Salesforce Metadata API 拉取元数据的功能。拉取的元数据以 Zip 文件形式返回,需要对这些 Zip 文件进行存储和解压处理。
|
||
|
||
本需求面临的主要问题包括:
|
||
1. Zip 文件存储需要支持本地文件系统和 OSS 存储两种方式
|
||
2. 需要处理大文件(可能达到数百 MB),避免内存溢出
|
||
3. 文件路径管理需要防止路径遍历攻击
|
||
4. 存储空间需要监控和告警机制
|
||
5. 需要自动清理过期文件以释放存储空间
|
||
|
||
相关约束条件:
|
||
- 必须基于现有的 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 处理路径,配合正则表达式验证路径安全性。
|
||
|
||
**理由**:
|
||
- `Path` API 提供了跨平台的路径处理能力
|
||
- `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)。
|
||
|
||
**优点**:
|
||
- 系统级支持,性能好
|
||
|
||
**缺点**:
|
||
- 与应用解耦,难以集成
|
||
- 配置不够灵活
|
||
- 不符合项目架构
|
||
|
||
## 影响
|
||
|
||
### 系统架构影响
|
||
|
||
1. **新增模块**: 在 `datai-salesforce-metadata` 模块下新增 `file` 包,包含文件存储、解压、路径管理等功能
|
||
2. **接口定义**: 定义 `IFileStorageService` 接口,提供统一的文件存储抽象
|
||
3. **策略模式**: 使用策略模式实现不同的存储策略,提高系统扩展性
|
||
4. **定时任务**: 新增两个定时任务(存储空间监控、文件清理),需要配置定时任务执行器
|
||
|
||
### 开发流程影响
|
||
|
||
1. **开发工作量**: 需要开发 5 个主要功能模块,预计工作量 3-5 人天
|
||
2. **测试工作量**: 需要进行单元测试、集成测试和性能测试,预计工作量 2-3 人天
|
||
3. **代码规范**: 需要遵循项目现有的代码规范和设计模式
|
||
4. **文档维护**: 需要更新接口文档和 API 文档
|
||
|
||
### 运维管理影响
|
||
|
||
1. **配置管理**: 需要新增配置项(存储类型、告警阈值、保留天数等)
|
||
2. **监控告警**: 需要配置存储空间监控和告警通知
|
||
3. **日志管理**: 需要记录文件操作日志和清理日志
|
||
4. **存储管理**: 需要定期检查存储空间使用情况
|
||
|
||
## 风险
|
||
|
||
### 技术风险
|
||
|
||
1. **大文件处理风险**: 大文件处理不当可能导致内存溢出
|
||
- **缓解措施**: 使用流式处理,限制内存占用
|
||
- **监控指标**: 监控 JVM 内存使用情况
|
||
|
||
2. **路径安全风险**: 路径验证不完善可能导致路径遍历攻击
|
||
- **缓解措施**: 使用 Path API 和正则表达式双重验证
|
||
- **监控指标**: 记录所有文件操作日志
|
||
|
||
3. **OSS 存储风险**: OSS 存储不稳定可能导致文件存储失败
|
||
- **缓解措施**: 实现重试机制和降级策略
|
||
- **监控指标**: 监控 OSS 存储成功率和响应时间
|
||
|
||
### 业务风险
|
||
|
||
1. **存储空间风险**: 存储空间不足可能导致文件存储失败
|
||
- **缓解措施**: 实现存储空间监控和告警机制
|
||
- **监控指标**: 监控存储空间使用率
|
||
|
||
2. **文件清理风险**: 文件清理策略不当可能导致重要文件被删除
|
||
- **缓解措施**: 清理前记录日志,支持文件恢复
|
||
- **监控指标**: 记录清理操作日志
|
||
|
||
### 实施风险
|
||
|
||
1. **性能风险**: 文件解压和清理可能影响系统性能
|
||
- **缓解措施**: 使用异步处理,限制并发数
|
||
- **监控指标**: 监控系统 CPU 和内存使用情况
|
||
|
||
2. **兼容性风险**: 不同操作系统的路径处理可能存在兼容性问题
|
||
- **缓解措施**: 使用 Java NIO 的 Path API,保证跨平台兼容性
|
||
- **监控指标**: 在不同操作系统上进行测试
|
||
|
||
## 回滚策略
|
||
|
||
### 1. 文件存储回滚策略
|
||
|
||
如果 OSS 存储出现问题,可以立即切换回本地文件系统:
|
||
1. 修改配置文件 `file.storage.type=local`
|
||
2. 重启应用
|
||
3. 将已存储到 OSS 的文件复制到本地文件系统
|
||
|
||
### 2. 文件解压回滚策略
|
||
|
||
如果流式解压出现问题,可以临时使用完整加载方式:
|
||
1. 修改代码,使用 `ZipFile` 替代 `ZipInputStream`
|
||
2. 限制文件大小,避免内存溢出
|
||
3. 优化后重新切换回流式解压
|
||
|
||
### 3. 文件清理回滚策略
|
||
|
||
如果文件清理出现问题,可以立即停止清理任务:
|
||
1. 修改配置文件,禁用定时任务
|
||
2. 恢复被误删的文件(如果有备份)
|
||
3. 修复清理策略后重新启用
|
||
|
||
### 4. 整体回滚策略
|
||
|
||
如果整个功能出现问题,可以回滚到 REQ-010-6 的状态:
|
||
1. 停止使用文件存储和解压功能
|
||
2. 将 Zip 文件临时存储在内存中
|
||
3. 修复问题后重新启用
|
||
|
||
## 验收标准
|
||
|
||
### 功能验收标准
|
||
|
||
1. **Zip 文件存储**
|
||
- [ ] 本地文件系统存储成功
|
||
- [ ] OSS 存储成功
|
||
- [ ] 存储路径正确
|
||
- [ ] 文件完整性验证通过
|
||
- [ ] 支持配置动态切换
|
||
|
||
2. **文件解压**
|
||
- [ ] 文件解压成功
|
||
- [ ] 支持大文件处理(> 100MB)
|
||
- [ ] 支持流式解压
|
||
- [ ] 内存使用合理(< 512MB)
|
||
- [ ] 解压文件结构正确
|
||
- [ ] 支持进度回调
|
||
- [ ] 支持取消操作
|
||
|
||
3. **文件路径管理**
|
||
- [ ] 文件路径管理正常工作
|
||
- [ ] 支持路径规范化
|
||
- [ ] 支持路径验证
|
||
- [ ] 路径格式正确
|
||
- [ ] 路径安全性验证通过
|
||
- [ ] 防止路径遍历攻击
|
||
|
||
4. **存储空间管理**
|
||
- [ ] 存储空间管理正常工作
|
||
- [ ] 支持存储空间监控
|
||
- [ ] 支持存储空间告警
|
||
- [ ] 存储空间信息准确
|
||
- [ ] 告警通知及时
|
||
|
||
5. **文件清理**
|
||
- [ ] 文件清理功能正常工作
|
||
- [ ] 支持过期文件自动清理
|
||
- [ ] 支持手动清理
|
||
- [ ] 清理策略可配置
|
||
- [ ] 清理日志记录完整
|
||
|
||
### 性能验收标准
|
||
|
||
1. **文件存储性能**
|
||
- [ ] 本地文件系统存储速度 > 50MB/s
|
||
- [ ] OSS 存储速度 > 20MB/s
|
||
- [ ] 并发存储 10 个文件无性能下降
|
||
|
||
2. **文件解压性能**
|
||
- [ ] 解压速度 > 30MB/s
|
||
- [ ] 内存使用 < 512MB
|
||
- [ ] 并发解压 5 个文件无性能下降
|
||
|
||
3. **存储空间监控性能**
|
||
- [ ] 监控任务执行时间 < 1s
|
||
- [ ] 不影响系统正常运行
|
||
|
||
4. **文件清理性能**
|
||
- [ ] 清理任务执行时间 < 5s
|
||
- [ ] 不影响系统正常运行
|
||
|
||
### 安全性验收标准
|
||
|
||
1. **路径安全**
|
||
- [ ] 防止路径遍历攻击
|
||
- [ ] 防止文件名注入攻击
|
||
- [ ] 防止符号链接攻击
|
||
|
||
2. **存储安全**
|
||
- [ ] 文件存储权限正确
|
||
- [ ] OSS 存储访问权限正确
|
||
- [ ] 文件完整性验证通过
|
||
|
||
### 代码质量验收标准
|
||
|
||
1. **代码规范**
|
||
- [ ] 代码符合项目编码规范
|
||
- [ ] 有清晰的注释
|
||
- [ ] 通过代码审查
|
||
|
||
2. **测试覆盖**
|
||
- [ ] 单元测试覆盖率 > 80%
|
||
- [ ] 集成测试覆盖主要场景
|
||
- [ ] 性能测试通过
|
||
|
||
3. **文档完整**
|
||
- [ ] 接口文档完整
|
||
- [ ] API 文档完整
|
||
- [ ] 使用文档完整
|
||
|
||
## 视觉锚点
|
||
|
||
### Visual Reference
|
||
|
||
引用 Canvas 的具体节点或快照:
|
||
- [Authentication.canvas](../../Authentication.canvas) - 项目架构视觉化展示
|
||
- **具体节点**: [集成核心](node_integration_core) - 提供与Salesforce的各种连接方式
|
||
|
||
### Status
|
||
|
||
- [x] Draft
|
||
- [ ] Accepted
|
||
- [ ] Superceded
|
||
|
||
## 参考资料
|
||
|
||
列出与该决策相关的参考资料,包括文档、文章或其他资源:
|
||
|
||
1. [REQ-010-7.md](../requirements/REQ-010-7.md) - 文件存储和解压处理需求文档
|
||
2. [REQ-010-6.md](../requirements/REQ-010-6.md) - 元数据拉取核心功能需求文档
|
||
3. [file/index.md](../api-docs/file/index.md) - 文件模块 API 文档索引
|
||
4. Java NIO Path API 文档: https://docs.oracle.com/javase/8/docs/api/java/nio/file/Path.html
|
||
5. Spring Boot 文件上传文档: https://docs.spring.io/spring-boot/docs/current/reference/html/web.html#web.servlet.spring-multipart
|
||
6. Apache Commons Compress 文档: https://commons.apache.org/proper/commons-compress/
|