feat: 更新公告和链接状态接口,增强参数校验,支持跳转链接最大长度为5000字符,添加异步保存完成图片功能,优化接口文档和数据库结构

This commit is contained in:
yahaozhang
2025-11-03 20:56:34 +08:00
parent f43320138a
commit cadf8d98cb
40 changed files with 3148 additions and 17 deletions

View File

@@ -0,0 +1,277 @@
# 完成图片保存重试机制
## 🔄 重试策略
为了确保4张完成图片都能成功保存系统实现了**双层重试机制**。
## 📊 重试架构
### 第一层网络层重试ScriptClient
**位置**: `ScriptClient.getImagePng()`
```java
.timeout(Duration.ofSeconds(10)) // 10秒超时
.retry(3) // 网络失败重试3次立即重试
```
**重试条件**:
- 网络连接失败
- HTTP错误
- 超时10秒
**重试间隔**: 立即重试(无延迟)
---
### 第二层业务层重试CompletionImageService
**位置**: `CompletionImageService.downloadAndSaveImage()`
```java
.retryWhen(Retry.fixedDelay(3, Duration.ofMillis(500))
.doBeforeRetry(retrySignal -> {
long attempt = retrySignal.totalRetries() + 1;
log.warn("下载图片失败,开始第{}次重试: codeNo={}, imageName={}",
attempt, codeNo, imageName);
})
)
```
**重试条件**:
- 图片下载失败
- 文件写入失败
- 任何异常
**重试间隔**: 500毫秒固定延迟
**重试次数**: 3次
---
## 🎯 完整重试流程
```mermaid
graph TD
A[开始下载图片] --> B[ScriptClient.getImagePng]
B --> C{成功?}
C -->|失败| D{第一层重试<3次?}
D -->|是| B
D -->|否| E[第一层失败]
C -->|成功| F[保存到文件系统]
E --> G{第二层重试<3次?}
F --> H{保存成功?}
H -->|失败| G
G -->|是| I[等待500ms]
I --> B
G -->|否| J[最终失败]
H -->|成功| K[保存成功]
```
## 📝 日志示例
### 成功场景(无重试)
```log
DEBUG - 开始下载图片: codeNo=MYNM5JHA, imageName=首次主页.png, scriptPath=/rr3/首次主页.png
DEBUG - 获取图片成功: path=/rr3/首次主页.png, 数据大小=245678字节
DEBUG - 图片保存成功: codeNo=MYNM5JHA, imageName=首次主页.png, size=245678字节, path=20251103/MYNM5JHA/homepage.png
```
### 重试场景(网络抖动)
```log
DEBUG - 开始下载图片: codeNo=MYNM5JHA, imageName=首次赏金.png, scriptPath=/rr3/首次赏金.png
WARN - 获取图片失败: path=/rr3/首次赏金.png, error=Connection timeout
WARN - 下载图片失败开始第1次重试: codeNo=MYNM5JHA, imageName=首次赏金.png
DEBUG - 获取图片成功: path=/rr3/首次赏金.png, 数据大小=189234字节
DEBUG - 图片保存成功: codeNo=MYNM5JHA, imageName=首次赏金.png, size=189234字节
```
### 最终失败场景
```log
DEBUG - 开始下载图片: codeNo=MYNM5JHA, imageName=结束赏金.png, scriptPath=/rr3/结束赏金.png
WARN - 获取图片失败: path=/rr3/结束赏金.png, error=404 Not Found
WARN - 下载图片失败开始第1次重试: codeNo=MYNM5JHA, imageName=结束赏金.png
WARN - 获取图片失败: path=/rr3/结束赏金.png, error=404 Not Found
WARN - 下载图片失败开始第2次重试: codeNo=MYNM5JHA, imageName=结束赏金.png
WARN - 获取图片失败: path=/rr3/结束赏金.png, error=404 Not Found
WARN - 下载图片失败开始第3次重试: codeNo=MYNM5JHA, imageName=结束赏金.png
WARN - 获取图片失败: path=/rr3/结束赏金.png, error=404 Not Found
ERROR - 下载图片失败已重试3次: codeNo=MYNM5JHA, imageName=结束赏金.png, 最后错误=404 Not Found
WARN - 图片下载和保存最终失败: codeNo=MYNM5JHA, imageName=结束赏金.png, error=404 Not Found
INFO - 完成图片保存成功: codeNo=MYNM5JHA, 成功数量=3/4
```
## 📊 重试统计
### 单张图片最多重试次数
**总重试次数 = 第一层重试 × 第二层重试**
- 第一层网络层3次立即重试
- 第二层业务层3次延迟重试每次500ms
- **理论最大尝试**1 + 3 + 3 = **7次**
- **实际有效重试**:约 **3-6次**(取决于失败类型)
### 超时时间
**单次尝试总超时**:
- 网络超时10秒
- 网络重试10s × 3 = 30秒
- **单次最长时间**约40秒
**整体超时**:
- 业务层重试间隔500ms × 3 = 1.5秒
- **最长总时间**约120秒极端情况
## 🎯 容错处理
### 部分图片失败不影响整体
即使某张图片下载失败,其他图片依然会保存成功:
```json
{
"saveTime": "2025-11-03T20:30:45",
"codeNo": "MYNM5JHA",
"machineId": "rr3",
"dateFolder": "20251103",
"images": {
"homepage": "20251103/MYNM5JHA/homepage.png",
"first-reward": "20251103/MYNM5JHA/first-reward.png",
"mid-reward": "20251103/MYNM5JHA/mid-reward.png"
// "end-reward" 下载失败,未保存
},
"totalCount": 3 // 成功保存3张
}
```
### 数据库记录
**成功数量会记录在 completion_images 字段中**:
```sql
SELECT
code_no,
JSON_EXTRACT(completion_images, '$.totalCount') as saved_count,
completion_images_saved_at
FROM link_task
WHERE code_no = 'MYNM5JHA';
-- 结果:
-- code_no: MYNM5JHA
-- saved_count: 3
-- completion_images_saved_at: 2025-11-03 20:30:45
```
## 🔍 故障排查
### 检查某个任务的图片保存情况
```bash
# 查看日志
grep "codeNo=MYNM5JHA" logs/server.log | grep "图片"
# 查看文件系统
ls -lh completion-images/$(date +%Y%m%d)/MYNM5JHA/
# 查询数据库
mysql> SELECT code_no,
JSON_EXTRACT(completion_images, '$.totalCount') as count,
completion_images
FROM link_task
WHERE code_no = 'MYNM5JHA'\G
```
### 常见失败原因
| 错误类型 | 说明 | 重试是否有效 | 解决方案 |
|---------|------|--------------|----------|
| **Connection timeout** | 网络超时 | ✅ 有效 | 自动重试通常能解决 |
| **404 Not Found** | 图片不存在 | ❌ 无效 | 检查脚本端是否生成图片 |
| **500 Server Error** | 脚本端错误 | ⚠️ 部分有效 | 检查脚本端服务状态 |
| **Permission denied** | 文件权限错误 | ❌ 无效 | 检查目录权限 |
| **Disk full** | 磁盘空间不足 | ❌ 无效 | 清理磁盘空间 |
## 📈 优化建议
### 1. 监控重试率
```sql
-- 统计图片保存成功率
SELECT
DATE(completion_images_saved_at) as date,
COUNT(*) as total_tasks,
SUM(CASE
WHEN JSON_EXTRACT(completion_images, '$.totalCount') = 4
THEN 1 ELSE 0
END) as all_4_images,
SUM(CASE
WHEN JSON_EXTRACT(completion_images, '$.totalCount') < 4
THEN 1 ELSE 0
END) as partial_images,
ROUND(SUM(CASE
WHEN JSON_EXTRACT(completion_images, '$.totalCount') = 4
THEN 1 ELSE 0
END) * 100.0 / COUNT(*), 2) as success_rate
FROM link_task
WHERE completion_images_saved_at IS NOT NULL
GROUP BY DATE(completion_images_saved_at)
ORDER BY date DESC;
```
### 2. 告警阈值
建议设置告警:
- 如果成功率 < 80%发送告警
- 如果某个图片重试率 > 50%,检查该图片源
### 3. 性能调优
```yaml
# application.yml - 可调整的参数
completion:
image:
retry:
max-attempts: 3 # 最大重试次数
delay-ms: 500 # 重试延迟(毫秒)
timeout-seconds: 10 # 单次下载超时
```
## ⚡ 性能影响
### 最佳情况(所有图片一次成功)
- **总耗时**: 约 2-4秒4张图片并发下载
- **网络请求**: 4次
### 一般情况有1-2次重试
- **总耗时**: 约 5-8秒
- **网络请求**: 4-8次
### 最坏情况(某些图片多次重试)
- **总耗时**: 约 10-15秒
- **网络请求**: 10-16次
- **成功保存**: 3-4张图片
## 🎉 优势
1. **高成功率**: 双层重试机制大幅提升成功率
2. **详细日志**: 每次重试都有日志记录,便于排查
3. **容错处理**: 部分失败不影响整体
4. **异步执行**: 不阻塞任务完成主流程
## 📋 监控指标
建议监控以下指标:
- ✅ 图片保存总成功率
- ✅ 每张图片的成功率
- ✅ 平均重试次数
- ✅ 平均保存耗时
- ✅ 失败原因分布
---
**更新时间**: 2025-11-03
**重试次数**: 每张图片最多3次
**重试延迟**: 500毫秒
**状态**: ✅ 已实现