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

5.0 KiB
Raw Blame History

任务卡住问题分析

问题现象

任务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: 检查任务状态

-- 查看任务详情
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相关的详细错误

# 在日志中搜索任务385
grep "任务 385" lover/logs/*.log

# 查看最近的错误
grep -i "error\|exception\|failed" lover/logs/*.log | tail -50

步骤3: 检查DashScope任务

如果有 dashscope_task_id可以查询DashScope任务状态

from dashscope import VideoSynthesis

task_id = "从数据库获取的dashscope_task_id"
result = VideoSynthesis.fetch(task_id)
print(result)

步骤4: 检查系统资源

# 检查内存使用
free -h

# 检查磁盘空间
df -h

# 检查Python进程
ps aux | grep python

解决方案

方案1: 强制标记为失败(立即生效)

执行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: 增加超时处理(预防未来问题)

在代码中添加超时机制:

# 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: 添加任务监控

创建定时任务,自动清理超时任务:

# 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. 修复当前卡住的任务

# 连接数据库
mysql -u root -prootx77 fastadmin

# 执行修复SQL
source xuniYou/修复卡住的任务.sql

2. 重启服务

# 双击运行
重启服务.bat

3. 验证修复

  • 检查任务385是否已标记为失败
  • 尝试重新生成视频
  • 观察新任务是否正常完成

预防措施

1. 设置合理的超时时间

# config.py
EMO_TASK_TIMEOUT_SECONDS = 600  # 10分钟
SING_TASK_TIMEOUT_SECONDS = 1800  # 30分钟

2. 添加重试机制

MAX_RETRIES = 3
RETRY_DELAY = 60  # 秒

3. 改进错误处理

  • 捕获所有异常
  • 记录详细的错误信息
  • 及时更新任务状态

4. 监控告警

  • 监控running状态超过一定时间的任务
  • 发送告警通知
  • 自动清理超时任务

总结

任务卡住通常是因为:

  1. 外部API调用超时DashScope
  2. 资源下载超时OSS
  3. 代码异常未正确处理

解决方法:

  1. 立即:手动标记为失败
  2. 短期:重启服务,增加超时处理
  3. 长期:添加监控和自动清理机制