211 lines
5.9 KiB
Markdown
211 lines
5.9 KiB
Markdown
# 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缓存管理器
|
||
- 集成到下载接口
|
||
- 支持版本控制和自动过期
|