Ai_GirlFriend/xuniYou/任务卡住问题分析.md
2026-03-02 18:57:11 +08:00

235 lines
5.0 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.

# 任务卡住问题分析
## 问题现象
任务385一直卡在 `running` 状态,从日志可以看到:
1. **不断重试**: 任务状态一直是 `running`,不断尝试处理
2. **undefined错误**: 出现多次 `undefined` 错误
3. **环境变量错误**: `uni.env., 'undefined'`
4. **状态存储错误**: `storedStates` 相关错误
## 可能的原因
### 1. EMO视频生成超时
- DashScope API调用时间过长
- 网络连接不稳定
- API配额限制
### 2. 音频/视频下载超时
- OSS资源下载慢
- 文件过大
- 网络问题
### 3. 分段视频卡住
- 某个分段视频生成失败但未正确处理
- 等待DashScope返回结果超时
- 并发限制导致任务排队
### 4. 数据库连接问题
- 长时间事务未提交
- 数据库锁等待
- 连接池耗尽
### 5. 代码逻辑问题
- 异常未正确捕获
- 无限循环或死锁
- 超时设置不合理
## 诊断步骤
### 步骤1: 检查任务状态
```sql
-- 查看任务详情
SELECT * FROM nf_generation_tasks WHERE id = 385\G
-- 查看分段视频状态
SELECT sv.*, ss.segment_index
FROM nf_song_segment_video sv
LEFT JOIN nf_song_segment ss ON sv.segment_id = ss.id
WHERE sv.song_id = (SELECT JSON_EXTRACT(payload, '$.song_id') FROM nf_generation_tasks WHERE id = 385)
ORDER BY ss.segment_index;
```
### 步骤2: 检查应用日志
查找任务385相关的详细错误
```bash
# 在日志中搜索任务385
grep "任务 385" lover/logs/*.log
# 查看最近的错误
grep -i "error\|exception\|failed" lover/logs/*.log | tail -50
```
### 步骤3: 检查DashScope任务
如果有 `dashscope_task_id`可以查询DashScope任务状态
```python
from dashscope import VideoSynthesis
task_id = "从数据库获取的dashscope_task_id"
result = VideoSynthesis.fetch(task_id)
print(result)
```
### 步骤4: 检查系统资源
```bash
# 检查内存使用
free -h
# 检查磁盘空间
df -h
# 检查Python进程
ps aux | grep python
```
## 解决方案
### 方案1: 强制标记为失败(立即生效)
执行SQL
```sql
UPDATE nf_generation_tasks
SET
status = 'failed',
error_msg = '任务处理超时,已手动标记为失败',
updated_at = NOW()
WHERE id = 385;
```
### 方案2: 重启服务(清理状态)
1. 停止Python服务
2. 执行方案1的SQL
3. 重启Python服务
### 方案3: 增加超时处理(预防未来问题)
在代码中添加超时机制:
```python
# lover/routers/sing.py
# 在_process_sing_task函数开始处添加
import signal
def timeout_handler(signum, frame):
raise TimeoutError("任务处理超时")
# 设置30分钟超时
signal.signal(signal.SIGALRM, timeout_handler)
signal.alarm(1800) # 30分钟
try:
# 原有的处理逻辑
...
finally:
signal.alarm(0) # 取消超时
```
### 方案4: 添加任务监控
创建定时任务,自动清理超时任务:
```python
# lover/task_cleanup.py
import schedule
import time
from db import SessionLocal
from models import GenerationTask
from datetime import datetime, timedelta
def cleanup_stuck_tasks():
"""清理卡住的任务"""
db = SessionLocal()
try:
# 查找超过30分钟的running任务
timeout = datetime.utcnow() - timedelta(minutes=30)
stuck_tasks = (
db.query(GenerationTask)
.filter(
GenerationTask.status == "running",
GenerationTask.updated_at < timeout
)
.all()
)
for task in stuck_tasks:
task.status = "failed"
task.error_msg = "任务处理超时超过30分钟"
task.updated_at = datetime.utcnow()
db.add(task)
db.commit()
print(f"清理了 {len(stuck_tasks)} 个超时任务")
finally:
db.close()
# 每5分钟检查一次
schedule.every(5).minutes.do(cleanup_stuck_tasks)
if __name__ == "__main__":
while True:
schedule.run_pending()
time.sleep(60)
```
## 立即操作
### 1. 修复当前卡住的任务
```bash
# 连接数据库
mysql -u root -prootx77 fastadmin
# 执行修复SQL
source xuniYou/修复卡住的任务.sql
```
### 2. 重启服务
```bash
# 双击运行
重启服务.bat
```
### 3. 验证修复
- 检查任务385是否已标记为失败
- 尝试重新生成视频
- 观察新任务是否正常完成
## 预防措施
### 1. 设置合理的超时时间
```python
# config.py
EMO_TASK_TIMEOUT_SECONDS = 600 # 10分钟
SING_TASK_TIMEOUT_SECONDS = 1800 # 30分钟
```
### 2. 添加重试机制
```python
MAX_RETRIES = 3
RETRY_DELAY = 60 # 秒
```
### 3. 改进错误处理
- 捕获所有异常
- 记录详细的错误信息
- 及时更新任务状态
### 4. 监控告警
- 监控running状态超过一定时间的任务
- 发送告警通知
- 自动清理超时任务
## 总结
任务卡住通常是因为:
1. 外部API调用超时DashScope
2. 资源下载超时OSS
3. 代码异常未正确处理
解决方法:
1. 立即:手动标记为失败
2. 短期:重启服务,增加超时处理
3. 长期:添加监控和自动清理机制