# PDF接口文档下载缓存优化说明 ## 📋 概述 本次优化为PDF接口文档下载功能添加了本地文件缓存机制,显著提升了下载性能,减少了重复生成PDF的开销。 ## 🔍 问题分析 ### 原有问题 1. **性能问题**: - 每次请求都重新生成PDF,没有缓存机制 - PDF生成涉及复杂的字体加载、页面构建、表格渲染等操作,耗时较长 - 同一产品的PDF被多次下载时,会重复执行相同的生成过程 2. **资源浪费**: - CPU资源浪费在重复的PDF生成上 - 数据库查询重复执行 - 没有版本控制,即使产品文档没有变化,也会重新生成 ## ✅ 解决方案 ### 1. PDF缓存管理器 (`PDFCacheManager`) 创建了专门的PDF缓存管理器,提供以下功能: - **本地文件缓存**:将生成的PDF文件保存到本地文件系统 - **版本控制**:基于产品ID和文档版本号生成缓存键,确保版本更新时自动失效 - **自动过期**:支持TTL(Time To Live)机制,自动清理过期缓存 - **大小限制**:支持最大缓存大小限制,防止磁盘空间耗尽 - **定期清理**:后台任务每小时自动清理过期文件 ### 2. 缓存键生成策略 ```go // 基于产品ID和文档版本号生成唯一的缓存键 cacheKey = MD5(productID + ":" + version) ``` - 当产品文档版本更新时,自动生成新的缓存 - 旧版本的缓存会在过期后自动清理 ### 3. 缓存流程 ``` 请求下载PDF ↓ 检查缓存是否存在且有效 ↓ ├─ 缓存命中 → 直接返回缓存的PDF文件 └─ 缓存未命中 → 生成PDF → 保存到缓存 → 返回PDF ``` ### 4. 集成到下载接口 修改了 `DownloadProductDocumentation` 方法: - **缓存优先**:首先尝试从缓存获取PDF - **异步保存**:生成新PDF后异步保存到缓存,不阻塞响应 - **缓存标识**:响应头中添加 `X-Cache: HIT/MISS` 标识,便于监控 ## 🚀 性能提升 ### 预期效果 1. **首次下载**:与之前相同,需要生成PDF(约1-3秒) 2. **后续下载**:直接从缓存读取(< 100ms),性能提升 **10-30倍** 3. **缓存命中率**:对于热门产品,缓存命中率可达 **80-90%** ### 响应时间对比 | 场景 | 优化前 | 优化后 | 提升 | |------|--------|--------|------| | 首次下载 | 1-3秒 | 1-3秒 | - | | 缓存命中 | 1-3秒 | < 100ms | **10-30倍** | | 版本更新后首次 | 1-3秒 | 1-3秒 | - | ## ⚙️ 配置说明 ### 环境变量配置 可以通过环境变量自定义缓存配置: ```bash # 缓存目录(默认:系统临时目录下的tyapi_pdf_cache) export PDF_CACHE_DIR="/path/to/cache" # 缓存过期时间(默认:24小时) export PDF_CACHE_TTL="24h" # 最大缓存大小(默认:500MB) export PDF_CACHE_MAX_SIZE="524288000" # 字节 ``` ### 默认配置 - **缓存目录**:系统临时目录下的 `tyapi_pdf_cache` - **TTL**:24小时 - **最大缓存大小**:500MB ## 📁 文件结构 ``` tyapi-server/ ├── internal/ │ └── shared/ │ └── pdf/ │ ├── pdf_cache_manager.go # 新增:PDF缓存管理器 │ ├── pdf_generator.go # 原有:PDF生成器 │ └── ... ├── internal/ │ └── infrastructure/ │ └── http/ │ └── handlers/ │ └── product_handler.go # 修改:集成缓存机制 └── internal/ └── container/ └── container.go # 修改:初始化缓存管理器 ``` ## 🔧 使用示例 ### 基本使用 缓存机制已自动集成,无需额外代码: ```go // 用户请求下载PDF GET /api/v1/products/{id}/documentation/download // 系统自动: // 1. 检查缓存 // 2. 缓存命中 → 直接返回 // 3. 缓存未命中 → 生成PDF → 保存缓存 → 返回 ``` ### 手动管理缓存 如果需要手动管理缓存(如产品更新后清除缓存): ```go // 使特定产品的缓存失效 cacheManager.InvalidateByProductID(productID) // 使特定版本的缓存失效 cacheManager.Invalidate(productID, version) // 清空所有缓存 cacheManager.Clear() // 获取缓存统计信息 stats, _ := cacheManager.GetCacheStats() ``` ## 📊 监控和日志 ### 日志输出 系统会记录以下日志: - **缓存命中**:`PDF缓存命中` - 包含产品ID、版本、文件大小 - **缓存未命中**:`PDF缓存未命中,开始生成PDF` - **缓存保存**:`PDF已缓存` - 包含产品ID、缓存键、文件大小 - **缓存清理**:`已清理过期缓存文件` - 包含清理数量和释放空间 ### 响应头标识 响应头中添加了缓存标识: - `X-Cache: HIT` - 缓存命中 - `X-Cache: MISS` - 缓存未命中 ## 🔒 安全考虑 1. **文件权限**:缓存文件权限设置为 `0644`,仅所有者可写 2. **目录隔离**:缓存文件存储在独立目录,不影响其他文件 3. **自动清理**:过期文件自动清理,防止磁盘空间耗尽 ## 🐛 故障处理 ### 缓存初始化失败 如果缓存管理器初始化失败,系统会: - 记录警告日志 - 继续正常运行(禁用缓存功能) - 所有请求都会重新生成PDF ### 缓存读取失败 如果缓存读取失败,系统会: - 记录警告日志 - 自动降级为重新生成PDF - 不影响用户体验 ## 🔄 后续优化建议 1. **分布式缓存**:考虑使用Redis等分布式缓存,支持多实例部署 2. **缓存预热**:在系统启动时预生成热门产品的PDF 3. **压缩存储**:对PDF文件进行压缩存储,节省磁盘空间 4. **缓存统计**:添加更详细的缓存统计和监控指标 5. **智能清理**:基于LRU等算法,优先清理不常用的缓存 ## 📝 更新日志 - **2024-12-XX**:初始版本,实现本地文件缓存机制 - 添加PDF缓存管理器 - 集成到下载接口 - 支持版本控制和自动过期