datai/datai-scenes/datai-scene-salesforce/docs/decisions/adr/0016-file-storage-and-extract.md

423 lines
13 KiB
Markdown
Raw Normal View History

# 架构决策记录 - 文件存储和解压处理
## 背景
在 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/