datai/docs/archive/decisions/adr/0016-file-storage-and-extract.md

423 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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