nkds

导航

 

MonkeyCode故障排查手册:常见问题诊断与解决

引言

"系统不出问题的时候,运维的价值是隐性的;系统出问题的时候,运维的能力是显性的。"

在上一篇文章中,我们详细介绍了如何为MonkeyCode构建监控告警体系。但监控只是第一步——当告警真的触发时,你能否快速定位根因并恢复服务?

本文将作为MonkeyCode运维团队的实战故障排查手册,覆盖从安装部署到日常运行中最常见的30+个问题场景,每个问题都包含:症状描述→排查步骤→解决方案→预防措施。

一、快速诊断决策树

╔═══════════════════════════════════════════════════════════╗
║         MonkeyCode 故障快速诊断                             ║
╠═══════════════════════════════════════════════════════════╣
║                                                           ║
║  问题现象?                                                ║
║                                                           ║
│  ┌────────────────┐                                       │
│  │ 完全无法连接?   │──是──→ 【第一节:连接问题】            │
│  └───────┬────────┘                                       │
│          │ 否                                             │
│  ┌───────▼────────┐                                       │
│  │ 连接但响应极慢? │──是──→ 【第二节:性能问题】            │
│  └───────┬────────┘                                       │
│          │ 否                                             │
│  ┌───────▼────────┐                                       │
│  │ 响应快但质量差? │──是──→ 【第三节:输出质量问题】        │
│  └───────┬────────┘                                       │
│          │ 否                                             │
│  ┌───────▼────────┐                                       │
│  │ IDE插件异常?    │──是──→ 【第四节:插件问题】            │
│  └───────┬────────┘                                       │
│          │ 否                                             │
│  ┌───────▼────────┐                                       │
│  │ GPU/模型相关?   │──是──→ 【第五节:GPU与模型问题】       │
│  └────────────────┘                                       │
║                                                           ║
╚═══════════════════════════════════════════════════════════╝

二、连接问题(完全无法使用)

问题2.1:服务启动失败

症状

$ monkeycode-server start
Error: Failed to bind to port 8080
Address already in use

排查步骤

# Step 1: 检查端口占用
sudo lsof -i :8080
# 或
ss -tlnp | grep 8080

# Step 2: 如果被占用,查看是什么进程
ps aux | grep $(lsof -t -i:8080)

# Step 3: 常见原因及处理
# 情况A: 上次进程没有正常退出
kill -9 $(lsof -t -i:8080)
monkeycode-server start

# 情况B: 端口配置冲突
# 编辑 config/server.yaml
# 修改 port: 8080 → port: 8081

# 情况C: Docker端口映射冲突
docker ps --format "table {{.Names}}\t{{.Ports}}" | grep 8080
# 修改 docker-compose.yml 中的端口映射

预防措施

# 在 systemd service 文件中添加
[Service]
ExecStartPre=/bin/bash -c 'kill -9 $(lsof -t -i:%i 2>/dev/null) || true'
Restart=on-failure
RestartSec=5
StartLimitBurst=5

问题2.2:API返回502/504错误

症状:浏览器访问MonkeyCode Web界面显示 "502 Bad Gateway" 或 "504 Gateway Timeout"

排查步骤

# Step 1: 检查各层状态
echo "=== Nginx/网关层 ==="
curl -s -o /dev/null -w "%{http_code}" http://localhost:80/health
# 期望: 200

echo "\n=== API服务层 ==="
curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/api/v1/health
# 期望: 200

echo "\n=== 推理服务层 ==="
curl -s -o /dev/null -w "%{http_code}" http://localhost:8000/health
# 期望: 200 (vLLM/TGI)

# Step 2: 查看网关日志
tail -100 /var/log/nginx/error.log | grep -i "upstream"

# Step 3: 检查上游超时设置
cat /etc/nginx/conf.d/monkeycode.conf
# 关键配置:
# proxy_connect_timeout 10s;
# proxy_read_timeout 300s;  # AI推理可能需要较长时间!
# proxy_send_timeout 60s;

常见原因与修复

原因 现象 修复
推理服务未启动 502 启动vLLM/TGI服务
推理服务启动中(加载模型) 502持续数分钟 正常现象,等待模型加载完成
单次请求超时 504 增大proxy_read_timeout到300s+
上游崩溃 随机502/504 检查上游日志和OOM

问题2.3:WebSocket连接断开

症状:IDE插件频繁断开重连,控制台报错 WebSocket closed with code 1006

排查步骤

// 浏览器开发者工具 → Network → WS 过滤
// 检查:
// 1. 连接建立是否成功 (Status Code: 101 Switching Protocols)
// 2. 断开前的最后消息
// 3. 关闭代码含义:
//    1000: 正常关闭
//    1001: 客户端离开
//    1006: 异常关闭(网络中断/服务端崩溃)
//    1011: 服务端遇到错误
//    1013: 服务端重启
# Nginx WebSocket 配置检查
location /ws {
    proxy_pass http://backend;
    proxy_http_version 1.1;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection "upgrade";
    
    # 关键:WebSocket超时设置
    proxy_read_timeout 86400s;   # 24小时(流式生成可能很长)
    proxy_send_timeout 86400s;
}

修复方案

# monkeycode.yaml — WebSocket 配置优化
websocket:
  heartbeat_interval: 30s      # 心跳间隔
  heartbeat_timeout: 90s       # 超过3次心跳未响应则断开
  max_message_size: "10MB"     # 大代码文件传输
  reconnect:
    max_attempts: 10           # 最大重连次数
    base_delay: "1s"           # 初始延迟
    max_delay: "30s"           # 最大延迟
    exponential_backoff: true  # 指数退避

三、性能问题(响应慢)

问题3.1:首次响应极慢(冷启动)

症状:第一次请求需要等待30秒-几分钟,后续请求正常

原因分析

┌─────────────────────────────────────────────────────────────┐
│         冷启动链路分析                                        │
│                                                             │
│  用户请求                                                    │
│    ↓                                                        │
│  [API网关] ───── 1ms ────→ [API服务]                        │
│                              ↓                              │
│                         [模型推理引擎] ←── 这里是瓶颈!      │
│                              ↓                              │
│                         ┌─────────────────────┐            │
│                         │ 1. 加载模型权重到GPU  │ ~30-120s   │
│                         │ 2. 编译计算图(Kernel) │ ~5-20s    │
│                         │ 3. 预热KV Cache       │ ~1-5s     │
│                         │ 4. 初始化采样器等     │ ~1s       │
│                         └─────────────────────┘            │
│                              ↓                              │
│                         开始推理                             │
└─────────────────────────────────────────────────────────────┘

解决方案

# 方案1: 预热脚本(在服务启动后立即执行)
import requests
import time

def warmup_model(base_url="http://localhost:8080"):
    """发送预热请求,让模型完成初始化"""
    warmup_prompts = [
        "// Write a hello world function",
        "def add(a, b):",
        "public class Hello {",
        "# TODO: implement",
    ]
    
    print("开始模型预热...")
    start = time.time()
    
    for i, prompt in enumerate(warmup_prompts):
        try:
            resp = requests.post(
                f"{base_url}/api/v1/generate",
                json={
                    "prompt": prompt,
                    "max_tokens": 50,
                    "stream": False,
                },
                timeout=120,
            )
            print(f"  预热请求 {i+1}/{len(warmup_prompts)} 完成")
        except Exception as e:
            print(f"  预热请求 {i+1} 失败: {e}")
            
    elapsed = time.time() - start
    print(f"✅ 预热完成,耗时 {elapsed:.1f}s")

if __name__ == "__main__":
    warmup_model()
# 方案2: vLLM 配置优化(减少冷启动时间)
server_args:
  # 使用更快的模型加载方式
  enable-prefix-caching: true    # 开启前缀缓存
  
  # 预分配显存(避免运行时分配导致抖动)
  gpu-memory-utilization: 0.95
  
  # 减少首次编译开销
  enforce-eager: false           # 使用CUDA graph加速
  
  # 并行优化
  tensor-parallel-size: 1       # 根据GPU数量调整
  pipeline-parallel-size: 1

问题3.2:响应逐渐变慢(性能衰减)

症状:刚重启时很快(<2s),运行几小时后变慢(>10s)

排查清单

#!/bin/bash
# MonkeyCode 性能衰减诊断脚本

echo "=========================================="
echo "  MonkeyCode 性能衰减诊断"
echo "=========================================="

echo ""
echo "[1] GPU显存碎片化检查..."
nvidia-smi --query-gpu=memory.used,memory.total,memory.free --format=csv,noheader
echo "如果 used 接近 total 但实际推理需求不大,可能有内存泄漏/碎片"

echo ""
echo "[2] GPU温度降频检查..."
nvidia-smi --query-gpu=temperature.gpu,clocks.current.sm,clocks.max.sm --format=csv,noheader
echo "如果 current.sm << max.sm,说明因高温降频"

echo ""
echo "[3] 进程内存泄漏检查..."
pid=$(pgrep -f "monkeycode|vllm")
if [ -n "$pid" ]; then
    echo "PID: $pid"
    cat /proc/$pid/status | grep VmRSS
    echo "观察该值是否持续增长"
fi

echo ""
echo "[4] KV Cache膨胀检查..."
# vLLM 的 KV Cache 会随着不同请求不断增长
curl -s http://localhost:8000/stats | python3 -m json.tool \
  | grep -E "cache_num|gpu_cache"

echo ""
echo "[5] 文件描述符耗尽检查..."
ulimit -n
ls /proc/$pid/fd/ 2>/dev/null | wc -l
echo "如果接近ulimit限制,需要增大或排查泄露"

echo ""
echo "[6] 网络连接池耗尽..."
ss -s | grep "estab"
echo "大量 ESTAB 连接可能是连接未释放"

常见原因与修复

原因 诊断命令 修复方案
KV Cache无限增长 /stats 中 cache_num 持续增 设置 max_num_seqs 和定期清理策略
GPU显存碎片 nvidia-smi 显示used高但利用率低 定期重启或启用显存整理
进程内存泄漏 VmRSS 持续增长 升级版本(已知bug)或设置定期重启
连接池耗尽 ss -s 显示大量ESTAB 调整连接池大小和idle timeout
日志文件过大 du -sh /var/log/monkeycode/ 配置logrotate

问题3.3:偶发超时(P99 spikes)

症状:大部分请求正常,但偶尔出现超过30秒的超时

排查方法

# analyze_latency_spikes.py
# 分析延迟尖峰的根因

import pandas as pd
import requests

# 从Prometheus获取延迟数据
query = """
histogram_quantile(0.99, 
    rate(monkeycode_request_duration_seconds_bucket[5m])
)
"""
resp = requests.get(
    "http://prometheus:9090/api/v1/query",
    params={"query": query}
)
data = resp.json()["data"]["result"]

# 找出尖峰时刻
df = pd.DataFrame([{
    "timestamp": d["values"][i][0],
    "value": float(d["values"][i][1])
} for d in data for i in range(len(d["values"]))])

spikes = df[df["value"] > df["value"].mean() + 3*df["value"].std()]
print(f"发现 {len(spikes)} 个延迟尖峰")

# 关联其他指标
for _, spike in spikes.iterrows():
    ts = spike["timestamp"]
    print(f"\n尖峰时刻: {ts}")
    
    # 检查同时刻的并发量
    concurrent = f'monkeycode_active_requests[{ts}]'
    # 检查同时刻的队列深度
    queue = f'monkeycode_queue_depth[{ts}]'
    # 检查同时刻的GPU利用率
    gpu_util = f'DCGM_FI_DEV_GPU_UTIL[{ts}]'
    # 检查是否有长尾请求(输入token特别多)
    input_tokens = f'rate(monkeycode_input_tokens_total[5m]) offset at {ts}'

典型场景与解决方案

场景A: 长尾大请求阻塞
现象:某个用户粘贴了整个文件(5000+ tokens),导致后续所有请求排队
解决:
  1. 设置最大输入长度限制(如 max_input_tokens=8192)
  2. 实现请求优先级队列(短请求优先)
  3. 对大请求自动拆分处理

场景B: GC停顿(Java服务)
现象:每隔几分钟出现一次规律性延迟尖峰
解决:
  1. 使用G1GC替代CMS/ZGC
  2. 调整GC参数: -XX:MaxGCPauseMillis=200
  3. 监控GC日志确认

场景C: 模型重新加载
现象:某时刻所有请求同时变慢
解决:
  1. 检查是否有定时任务触发模型切换
  2. 使用蓝绿部署避免重启期间服务中断
  3. 预加载下一版模型到备用GPU

四、输出质量问题(AI生成的代码不好用)

问题4.1:生成的代码风格不一致

症状:有时用驼峰命名,有时用下划线;有时用async/await,有时用回调

排查方向

diagnosis_checklist:
  
  system_prompt_check:
    question: "系统提示词中是否明确指定了编码规范?"
    fix: |
      在MonkeyCode的系统提示词中添加:
      "请严格遵循以下编码规范:
      - 命名:驼峰命名法(camelCase)用于变量/函数,帕斯卡(PascalCase)用于类
      - 缩进:4空格
      - 异步:统一使用 async/await
      - 注释:公共API必须有JSDoc"
      
  model_temperature_check:
    question: "temperature设置是否过高?"
    detail: "temperature越高,输出的随机性越大,风格越不稳定"
    recommended_values:
      code_generation: "0.1 - 0.3"  # 代码生成要低
      creative_writing: "0.7 - 1.0"  # 创意写作可以高
      
  context_conflict_check:
    question: "RAG检索到的上下文是否来自不同风格的代码?"
    fix: |
      1. 检索结果增加风格过滤
      2. 只检索同一项目/团队的代码
      3. 在提示词中明确"以第一个代码片段的风格为准"
      
  finetune_check:
    question: "是否使用了定制化微调模型?"
    recommendation: |
      如果团队有明确的编码规范,
      强烈建议使用LoRA微调(参见《定制化训练》一文)
      微调后的模型风格一致性可提升至85%+

问题4.2:生成代码存在安全漏洞

症状:AI生成的代码包含SQL注入、XSS、硬编码密码等问题

排查与修复

# security_filter_example.py
# MonkeyCode 安全过滤中间件示例

import re
from dataclasses import dataclass

@dataclass
class SecurityIssue:
    severity: str  # critical/high/medium/low
    category: str
    description: str
    line_number: int
    pattern: str

SECURITY_PATTERNS = [
    # SQL注入
    (r'execute\(["\'].*\+.*["\']', "critical", "SQL Injection",
     "字符串拼接构造SQL,应使用参数化查询"),
    (r'f"\s*SELECT.*\{.*\}', "critical", "SQL Injection (f-string)",
     "f-string直接拼接SQL变量"),
    
    # XSS
    (r'dangerouslySetInnerHTML', "high", "XSS",
     "使用dangerouslySetInnerHTML可能导致XSS"),
    (r'\.innerHTML\s*=', "high", "XSS",
     "innerHTML赋值应先做转义"),
    
    # 硬编码敏感信息
    (r'password\s*=\s*["\'][^"\']+["\']', "critical", "Hardcoded Password",
     "密码不应硬编码在源码中"),
    (r'secret_key\s*=\s*["\'][^"\']+["\']', "critical", "Hardcoded Secret",
     "密钥应从环境变量或密钥管理服务获取"),
    (r'api_key\s*=\s*["\'][^"\']+["\']', "high", "Hardcoded API Key",
     "API Key不应硬编码"),
    
    # 不安全的随机数
    (r'random\(\)', "medium", "Insecure Random",
     "Math.random()不适用于安全场景,应使用crypto.randomBytes()"),
    
    # 命令注入
    (r'exec\(["\'].*\+.*["\']', "critical", "Command Injection",
     "exec函数参数拼接用户输入可能导致命令注入"),
    (r'os\.system\(.+\.)', "critical", "Command Injection",
     "os.system参数含变量时有注入风险"),
    
    # 弱加密
    (r'md5\(', "low", "Weak Hash",
     "MD5不适合密码存储,应使用bcrypt/scrypt/argon2"),
]

def scan_generated_code(code: str) -> list[SecurityIssue]:
    """扫描AI生成的代码中的安全问题"""
    issues = []
    lines = code.split('\n')
    
    for pattern, severity, category, description in SECURITY_PATTERNS:
        for i, line in enumerate(lines, 1):
            if re.search(pattern, line):
                issues.append(SecurityIssue(
                    severity=severity,
                    category=category,
                    description=description,
                    line_number=i,
                    pattern=pattern,
                ))
    
    return issues


# 集成到MonkeyCode输出管道
def post_process_ai_output(generated_code: str) -> dict:
    """对AI输出进行安全扫描"""
    issues = scan_generated_code(generated_code)
    
    if not issues:
        return {"safe": True, "code": generated_code}
    
    critical_issues = [i for i in issues if i.severity == "critical"]
    
    if critical_issues:
        return {
            "safe": False,
            "code": None,
            "issues": issues,
            "action": "BLOCKED",  # 阻止输出
            "message": f"发现 {len(critical_issues)} 个严重安全问题,已阻止输出",
        }
    else:
        return {
            "safe": True,  # 允许输出但附带警告
            "code": generated_code,
            "issues": issues,
            "action": "WARNING",
            "message": f"发现 {len(issues)} 个安全问题,建议审查",
        }

问题4.3:模型出现幻觉(编造不存在的API/库)

症状:AI自信地使用了一个根本不存在的方法或库

缓解措施

hallucination_mitigation:
  
  strategy_1_context_grounding:
    name: "上下文锚定"
    method: |
      在提示词中强制要求只使用项目中已有的依赖:
      "本项目使用的库版本如下(只能使用以下库中的API):
      - spring-boot: 3.2.0
      - mybatis-plus: 3.5.5
      - hutool: 5.8.25
      不要使用任何不在上述列表中的库"
      
  strategy_2_verification_layer:
    name: "验证层"
    implementation: |
      AI输出后,通过以下验证:
      1. import语句检查:引用的包是否在pom.xml/requirements.txt中
      2. API签名检查:调用的方法是否存在于对应版本的SDK文档
      3. 类型检查:变量类型和方法签名是否匹配
      
  strategy_3_few_shot_with_examples:
    name: "少样本示例约束"
    method: |
      在提示词中提供3-5个正确的代码示例,
      让模型模仿这些示例的模式,
      显著降低幻觉率(研究显示可降低40-60%)
      
  strategy_4_temperature_control:
    name: "低温度参数"
    setting: "code_generation temperature = 0.1"
    effect: "降低创造性输出,提高事实准确性"

五、IDE插件问题

问题5.1:VSCode插件无响应

症状:VSCode中MonkeyCode面板空白,或输入框无反应

排查步骤

# Step 1: 检查插件进程
code --list-extensions | grep monkeycode

# Step 2: 查看插件日志
# VSCode → 输出(Ctrl+Shift+U) → 选择 "MonkeyCode"
# 或查看日志文件:
# macOS: ~/Library/Application Support/Code/logs/
# Linux: ~/.config/Code/logs/
# Windows: %APPDATA%/Code/logs/

# Step 3: 常见问题快速修复

# 问题A: Node.js版本不兼容
node --version
# 需要 >= 18.0.0

# 问题B: 扩展宿主崩溃
# Ctrl+Shift+P → "Developer: Restart Extension Host"

# 问题C: 代理设置问题
# 检查 VSCode 设置中的 proxy 配置
# MonkeyCode插件需要能访问API服务器

完整重装流程

# 1. 卸载旧版本
code --uninstall-extension monkeycode.monkeyCode-vscode

# 2. 清理残留数据
rm -rf ~/.vscode/extensions/monkeycode.*
rm -rf ~/AppData/Roaming/Code/User/globalStorage/monkeycode.*

# 3. 重新安装
code --install-extension monkeycode-1.2.3.vsix

# 4. 重启VSCode
code --disable-extensions  # 先以无扩展模式启动测试
# 确认基础功能OK后再启用扩展

问题5.2:JetBrains插件快捷键冲突

症状:MonkeyCode的快捷键触发了IDE的其他功能

解决方法

<!-- IntelliJ IDEA keymap配置 -->
<!-- Settings → Keymap → 搜索 "monkeycode" -->

<!-- 推荐的快捷键映射 -->
<keymap version="1" name="MonkeyCode Custom" parent="Default">
    <!-- 补全触发 -->
    <action id="monkeycode.complete">
        <keyboard-shortcut first-keystroke="ctrl space"/>
    </action>
    
    <!-- 内联补全接受 -->
    <action id="monkeycode.accept-inline">
        <keyboard-shortcut first-keystroke="tab"/>
    </action>
    
    <!-- 打开对话面板 -->
    <action id="monkeycode.open-chat">
        <keyboard-shortcut first-keystroke="ctrl shift m"/>
    </action>
    
    <!-- 解释选中代码 -->
    <action id="monkeycode.explain">
        <keyboard-shortcut first-keystroke="ctrl shift e"/>
    </action>
</keymap>

问题5.3:插件与服务端认证失败

症状:插件界面显示 "Authentication failed" 或 "Token expired"

排查与修复

# Step 1: 检查Token有效性
curl -H "Authorization: Bearer YOUR_TOKEN" \
  https://your-monkeyCode-server/api/v1/me

# Step 2: 常见原因
# A) Token过期(默认24小时有效期)
# 解决:插件设置 → Refresh Token

# B) 时钟偏差(服务端和客户端时间差>5分钟)
date  # 检查系统时间
ntpdate pool.ntp.org  # 同步时间

# C) SSO/LDAP集成问题
# 检查LDAP服务是否可用
ldapsearch -x -H ldap://corpdc.corp -b "DC=corp,DC=com" "(sAMAccountName=username)"

# Step 3: 重新获取Token
curl -X POST https://your-monkeyCode-server/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{"username":"your-user","password":"your-pass"}'

六、GPU与模型问题

问题6.1:CUDA Out of Memory (OOM)

症状:错误信息 RuntimeError: CUDA out of memory

紧急处理

# oom_emergency_handler.py
# OOM发生时的应急处理脚本

import subprocess
import requests

def handle_oom():
    """OOM应急处理流程"""
    
    print("🚨 检测到GPU OOM!执行应急处理...")
    
    # 1. 立即记录现场
    subprocess.run("nvidia-smi > /tmp/oom_nvidia_smi.log", shell=True)
    subprocess.run("free -h > /tmp/oom_memory.log", shell=True)
    
    # 2. 清理当前批次的挂起请求
    requests.post("http://localhost:8080/admin/cancel-pending-requests")
    
    # 3. 尝试释放显存
    import torch
    if torch.cuda.is_available():
        torch.cuda.empty_cache()
        print(f"✅ 已清理CUDA缓存,释放显存")
    
    # 4. 降低batch size
    requests.post("http://localhost:8080/admin/config", json={
        "max_batch_size": 1,  # 临时降到最低
        "max_num_seqs": 16,   # 减少并发序列
    })
    
    # 5. 切换到更小的模型(如果有配置)
    requests.post("http://localhost:8080/admin/switch-model", json={
        "model": "qwen2.5-coder-1.5b-instruct",  # 备用小模型
        "reason": "OOM emergency fallback"
    })
    
    print("✅ 应急处理完成,服务已降级运行")
    print("📋 请查看日志排查OOM根因:/tmp/oom_*.log")

根因分析与长期解决

oom_root_causes_and_fixes:
  
  cause_1_large_batch:
    symptom: "单次请求batch太大"
    diagnosis: "检查请求的 max_tokens 和 n 参数"
    fix: |
      限制前端传入的最大值:
      max_tokens: <= 2048 (默认)
      n (并行生成): <= 1 (生产环境不建议并行)
      
  cause_2_long_context:
    symptom: "输入序列过长"
    example: "用户粘贴了整个项目的代码"
    fix: |
      设置 max_model_len 限制
      超长输入自动截断并提示用户
      
  cause_3_memory_fragmentation:
    symptom: "总显存够但连续块不够"
    diagnosis: "nvidia-smi显示有free memory但仍OOM"
    fix: |
      启用显存整理(需要PyTorch 2.0+)
      或定期重启服务(如每天凌晨)
      
  cause_4_other_gpu_processes:
    symptom: "其他程序占用了显存"
    diagnosis: "nvidia-smi看到非MonkeyCode进程占用GPU"
    fix: |
      确保独占GPU使用(nvidia-smi -c 1)
      或使用CUDA_VISIBLE_DEVICES隔离
      
  cause_5_model_too_large_for_gpu:
    symptom: "模型本身就需要比物理显存更多的空间"
    example: "33B模型在24GB显卡上"
    fix: |
      使用量化模型(4bit/8bit量化可将显存需求降低2-4倍)
      或使用CPU offload(速度会下降)

问题6.2:模型加载失败

症状

FileNotFoundError: No such file or directory: 'models/qwen2.5-coder/pytorch_model.bin'
ValueError: Config file not found: config.json

排查与修复

#!/bin/bash
# 模型加载问题诊断脚本

MODEL_DIR="/opt/models/qwen2.5-coder"

echo "[1] 检查模型目录是否存在..."
if [ ! -d "$MODEL_DIR" ]; then
    echo "❌ 目录不存在: $MODEL_DIR"
    echo "请检查模型下载是否完整"
    exit 1
fi
echo "✅ 目录存在"

echo ""
echo "[2] 检查必需文件..."
REQUIRED_FILES=("config.json" "tokenizer.json" "tokenizer_config.json" 
                "special_tokens_map.json" "generation_config.json")
WEIGHT_FILES=("model.safetensors.index.json" "model-00001-of-0000X.safetensors")

for f in "${REQUIRED_FILES[@]}"; do
    if [ -f "$MODEL_DIR/$f" ]; then
        echo "✅ $f"
    else
        echo "❌ 缺少: $f"
    fi
done

echo ""
echo "[3] 检查模型权重文件..."
if [ -f "$MODEL_DIR/model.safetensors.index.json" ]; then
    echo "找到分片索引,检查分片完整性..."
    cat "$MODEL_DIR/model.safetensors.index.json" | python3 -c "
import sys, json
data = json.load(sys.stdin)
total = len(data['weight_map'])
print(f'  总共 {total} 个权重文件')
# 检查每个分片是否存在
from collections import Counter
files = Counter(data['weight_map'].values())
for fname, count in files.items():
    import os
    exists = os.path.exists(f'$MODEL_DIR/{fname}')
    status = '✅' if exists else '❌ 缺失!'
    print(f'  {status} {fname} ({count} tensors)')
"
elif [ -f "$MODEL_DIR/pytorch_model.bin" ] || [ -f "$MODEL_DIR/model.safetensors" ]; then
    echo "✅ 单文件权重存在"
else
    echo "❌ 未找到任何权重文件!"
fi

echo ""
echo "[4] 检查文件完整性(SHA256)..."
if [ -f "$MODEL_DIR/checksum.sha256" ]; then
    cd "$MODEL_DIR"
    sha256sum -c checksum.sha256
else
    echo "⚠️ 无校验文件,跳过完整性检查"
fi

echo ""
echo "[5] 检查权限..."
ls -la "$MODEL_DIR"/*.json "$MODEL_DIR"/*.safetensors 2>/dev/null | head -5
echo "确保运行用户至少有读权限(r--)"

问题6.3:多GPU环境下的NCCL通信错误

症状

NCCL ERROR: Collective communication failed
RuntimeError: NCCL error: unhandled cuda error (either device-side error or synchronous error)

解决方案

#!/bin/bash
# NCCL通信问题修复指南

echo "=========================================="
echo "  MonkeyCode NCCL 问题诊断与修复"
echo "=========================================="

# 1. 检查GPU互联拓扑
echo ""
echo "[1] GPU拓扑结构..."
nvidia-smi topo -m
# 期望看到 NVLINK 或 PIX (PCIe) 连接
# NVLINK 通信效率 >> PCIe

# 2. 检查NCCL调试信息
echo ""
echo "[2] 启用NCCL调试模式..."
export NCCL_DEBUG=INFO
export NCCL_DEBUG_SUBSYS=ALL
# 重现问题,观察详细日志

# 3. 常见NCCL问题修复
echo ""
echo "[3] 应用NCCL修复..."

# 修复A: 禁用P2P(某些虚拟化/云环境不支持)
export NCCL_P2P_DISABLE=1
export NCCL_IB_DISABLE=1  # 同时禁用InfiniBand(如果不使用)

# 修复B: 设置通信算法
export NCCL_ALGO=Ring  # Ring算法兼容性最好
# 其他选项: Tree, CollnetDirect

# 修复C: 超时设置
export NCCL_TIMEOUT=600  # 10分钟超时(模型加载可能较慢)

# 修复D: 环境感知缓冲区大小
export NCCL_BUFFSIZE=8388608  # 8MB

# 4. 网络相关(多节点场景)
echo ""
echo "[4] 多节点网络检查..."
if [ -n "$MONKEYCODE_MULTI_NODE" ]; then
    # 检查防火墙
    nc -zv $(hostname) 29500  # NCCL默认端口范围起始
    
    # 检查网卡绑定
    ibdev2netdev  # InfiniBand
    ethtool -i eth0  # 以太网
fi

echo ""
echo "✅ NCCL配置建议已输出"
echo "将上述 export 命令加入启动脚本即可生效"

七、数据库与存储问题

问题7.1:向量数据库查询超时

症状:RAG检索阶段耗时超过10秒

诊断与优化

# vector_db_tuning.py
# 向量数据库性能优化

# Milvus 优化配置
milvus_optimization = {
    "index_type": "IVF_FLAT",  # 精度最高
    # 或 IVF_PQ (更快,精度略低)
    # 或 HNSW (最佳平衡)
    
    "index_params": {
        "nlist": 1024,         # IVF聚类数量
        "M": 32,               # HNSW每个节点连接数
        "efConstruction": 200, # HNSW构建参数
    },
    
    "search_params": {
        "nprobe": 32,          # IVF搜索探测聚类数(越大越准但越慢)
        "ef": 128,             # HNSW搜索范围
    },
    
    "collection_settings": {
        "segments_per_query": 1,  # 减少段数提升查询速度
        "consistency_level": "Bounded",  # 牺牲一点一致性换取性能
    },
}

# 性能对比参考
# IVF_FLAT, nlist=1024, nprobe=32: 召回率95%, QPS~500
# HNSW, M=32, ef=128:          召回率97%, QPS~800
# IVF_PQ, m=64, nbits=8:       召回率85%, QPS~2000

问题7.2:Redis连接池耗尽

症状Cannot acquire connection from poolConnection pool exhausted

修复

# monkeycode redis 配置优化
redis:
  host: "redis-cluster.internal"
  port: 6379
  mode: "cluster"  # 或 standalone/sentinel
  
  connection_pool:
    max_connections: 50        # 最大连接数
    min_idle: 10              # 最小空闲连接
    max_idle: 30              # 最大空闲连接
    retry_on_timeout: true    # 超时自动重试
    
  timeouts:
    connect_timeout: 5s       # 连接超时
    socket_timeout: 10s       # 读写超时
    command_timeout: 5s       # 命令超时
    
  health_check:
    interval: 10s             # 健康检查间隔
    failure_threshold: 3      # 连续失败多少次标记不可用

八、故障排查工具箱

8.1 一键诊断脚本

#!/bin/bash
# monkeycode_diagnosis.sh
# MonkeyCode 全方位一键诊断工具

set -euo pipefail

RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

PASS=0
WARN=0
FAIL=0

check() {
    local label="$1"
    local condition="$2"
    local severity="${3:-FAIL}"
    
    if eval "$condition" > /dev/null 2>&1; then
        echo -e "${GREEN}✅ ${label}${NC}"
        ((PASS++))
    else
        if [ "$severity" = "WARN" ]; then
            echo -e "${YELLOW}⚠️  ${label}${NC}"
            ((WARN++))
        else
            echo -e "${RED}❌ ${label}${NC}"
            ((FAIL++))
        fi
    fi
}

info() {
    echo -e "${BLUE}ℹ️  $1${NC}"
}

echo "╔══════════════════════════════════════════════════╗"
echo "║     🐒 MonkeyCode 全方位诊断 v2.0               ║"
echo "║     $(date '+%Y-%m-%d %H:%M:%S')                   ║"
echo "╚══════════════════════════════════════════════════╝"
echo ""

# ===== 系统资源 =====
echo "━━━ 系统资源 ━━━"

check "CPU核心数 >= 4" "$(nproc) >= 4"
check "内存 >= 16GB" "$(free -g | awk '/Mem:/ {print $2}') -ge 16"
check "磁盘剩余 >= 50GB" "$(df -BG / | awk 'NR==2 {print $4}' | tr -d 'G') -ge 50"
check "系统负载 < CPU核数*2" "$(awk '{printf "%.0f", $1/$2*100}' /proc/loadavg) -lt 200" WARN

# ===== GPU =====
echo ""
echo "━━━ GPU 状态 ━━━"

if command -v nvidia-smi &> /dev/null; then
    GPU_COUNT=$(nvidia-smi --list-gpus | wc -l)
    check "NVIDIA驱动已安装" "true"
    check "检测到GPU ($GPU_COUNT 块)" "$GPU_COUNT -gt 0"
    
    GPU_TEMP=$(nvidia-smi --query-gpu=temperature.gpu --format=csv,noheader,nounits | sort -rn | head -1)
    check "GPU最高温度 < 85°C" "$GPU_TEMP -lt 85" WARN
    
    GPU_MEM_USED=$(nvidia-smi --query-gpu=memory.used --format=csv,noheader,nounits | awk '{s+=$1} END {print s}')
    GPU_MEM_TOTAL=$(nvidia-smi --query-gpu=memory.total --format=csv,noheader,nounits | awk '{s+=$1} END {print s}')
    GPU_MEM_PCT=$((GPU_MEM_USED * 100 / GPU_MEM_TOTAL))
    check "GPU显存使用 < 90%" "$GPU_MEM_PCT -lt 90" WARN
    
    info "GPU显存: ${GPU_MEM_USED}MB / ${GPU_MEM_TOTAL}MB (${GPU_MEM_PCT}%)"
    info "GPU最高温度: ${GPU_TEMP}°C"
else
    echo -e "${YELLOW}⚠️  未检测到nvidia-smi(可能无GPU或驱动未安装)${NC}"
    ((WARN++))
fi

# ===== Docker/K8s =====
echo ""
echo "━━━ 容器运行时 ━━━"

if command -v docker &> /dev/null; then
    check "Docker服务运行中" "docker info > /dev/null 2>&1"
    
    MC_CONTAINER=$(docker ps --filter "name=monkeycode" --format "{{.Names}}" | head -1)
    if [ -n "$MC_CONTAINER" ]; then
        info "容器名称: $MC_CONTAINER"
        check "容器状态为running" "docker inspect -f '{{.State.Status}}' $MC_CONTAINER | grep -q running"
        
        CONTAINER_UPTIME=$(docker inspect -f '{{.State.StartedAt}}' $MC_CONTAINER)
        info "启动时间: $CONTAINER_UPTIME"
        
        RESTART_COUNT=$(docker inspect -f '{{.RestartCount}}' $MC_CONTAINER)
        check "容器重启次数 < 5" "$RESTART_COUNT -lt 5" WARN
        
        if [ "$RESTART_COUNT" -gt 0 ]; then
            info "⚠️  容器已重启 $RESTART_COUNT 次"
            info "最近退出码: $(docker inspect -f '{{.State.ExitCode}}' $MC_CONTAINER)"
        fi
    else
        echo -e "${RED}❌ 未找到运行中的MonkeyCode容器${NC}"
        ((FAIL++))
    fi
fi

# ===== 网络连通性 =====
echo ""
echo "━━━ 网络连通性 ━━━"

check "DNS解析正常" "nslookup github.com > /dev/null 2>&1"
check "API端口可达" "curl -sf --connect-timeout 3 http://localhost:8080/api/v1/health > /dev/null" WARN
check "外部网络可达" "curl -sf --connect-timeout 3 https://www.google.com > /dev/null 2>&1" WARN

# ===== 依赖服务 =====
echo ""
echo "━━━ 依赖服务 ━━━"

check "Redis可达" "redis-cli -h localhost -p 6379 ping 2>/dev/null | grep -q PONG" WARN
check "PostgreSQL可达" "pg_isready -h localhost -p 5432 2>/dev/null | grep -q accepting" WARN
check "Milvus可达" "curl -sf http://localhost:9091/healthz > /dev/null 2>&1" WARN

# ===== MonkeyCode服务健康 =====
echo ""
echo "━━━ MonkeyCode 服务 ━━━"

HEALTH_RESP=$(curl -sf http://localhost:8080/api/v1/health 2>/dev/null || echo "{}")
if [ -n "$HEALTH_RESP" ] && [ "$HEALTH_RESP" != "{}" ]; then
    check "API服务健康端点正常" "true"
    echo "$HEALTH_RESP" | python3 -m json.tool 2>/dev/null || echo "$HEALTH_RESP"
else
    echo -e "${RED}❌ API服务健康检查失败${NC}"
    ((FAIL++))
fi

# ===== 总结 =====
echo ""
echo "╔══════════════════════════════════════════════════╗"
echo "║                 诊断总结                       ║"
echo "╠══════════════════════════════════════════════════╣"
echo -e "║  ${GREEN}通过: ${PASS}${NC}  ${YELLOW}警告: ${WARN}${NC}  ${RED}失败: ${FAIL}${NC}          ║"
echo "╚══════════════════════════════════════════════════╝"

if [ "$FAIL" -gt 0 ]; then
    echo ""
    echo -e "${RED}🔴 发现 ${FAIL} 个严重问题,请按上述提示逐一修复${NC}"
    exit 1
elif [ "$WARN" -gt 0 ]; then
    echo ""
    echo -e "${YELLOW}🟡 发现 ${WARN} 个警告项,建议尽快处理${NC}"
    exit 0
else
    echo ""
    echo -e "${GREEN}🟢 所有检查通过!MonkeyCode运行状态良好${NC}"
    exit 0
fi

8.2 日志分析常用命令

# ===== 实时日志跟踪 =====
# 跟踪所有ERROR级别日志
tail -f /var/log/monkeycode/app.log | grep -i "error\|exception\|fatal"

# 跟踪特定用户的请求
tail -f /var/log/monkeycode/app.log | grep "user_id=abc123"

# 跟踪慢请求(>5秒)
tail -f /var/log/monkeycode/app.log | grep "duration=[5-9][0-9]\{3,\}\|duration=[1-9][0-9]\{4,\}"

# ===== 统计分析 =====
# 最近1小时的错误统计
grep "ERROR" /var/log/monkeycode/app.log | awk '{print $1}' | sort | uniq -c | sort -rn | head -20

# P99延迟趋势(每5分钟一个点)
awk '/duration=/{match($0, /duration=([0-9]+)/, a); print a[1]}' \
  /var/log/monkeycode/app.log | sort -n | tail -n +$(($(wc -l < /dev/stdin)*99/100)) \
  | awk 'NR%100==0'

# 各类型请求的分布
grep "endpoint=" /var/log/monkeycode/app.log \
  | sed 's/.*endpoint=\([^ ]*\).*/\1/' | sort | uniq -c | sort -rn

# ===== GPU相关 =====
# GPU OOM历史
grep -i "oom\|cuda out of memory\|killed" /var/log/monkeycode/app.log \
  | tail -20

# 模型加载记录
grep -i "loading model\|model loaded\|warmup" /var/log/monkeycode/app.log \
  | tail -10

九、常见问题速查表

# 问题现象 可能原因 快速修复 详细章节
1 服务无法启动 端口占用 lsof -i :port + kill §2.1
2 502 Bad Gateway 上游未启动 检查vLLM/TGI进程 §2.2
3 WebSocket断开 超时配置太短 增大read_timeout §2.3
4 首次请求很慢 冷启动 预热脚本 §3.1
5 运行几小时后变慢 内存泄漏/GC 检查VmRSS §3.2
6 偶发超时 长尾请求阻塞 限流+队列 §3.3
7 代码风格不一致 温度过高/无规范 降temp+加规范 §4.1
8 生成代码有漏洞 无安全过滤 加安全扫描层 §4.2
9 AI编造API 幻觉问题 低temp+上下文锚定 §4.3
10 VSCode插件无响应 扩展宿主崩溃 重启Extension Host §5.1
11 快捷键冲突 与IDE内置冲突 自定义Keymap §5.2
12 认证失败 Token过期 Refresh Token §5.3
13 CUDA OOM 显存不足 降batch/切小模型 §6.1
14 模型加载失败 文件缺失/损坏 运行诊断脚本 §6.2
15 NCCL通信错误 多GPU配置不当 设NCCL环境变量 §6.3
16 向量库查询慢 索引未优化 调整index参数 §7.1
17 Redis连接池耗尽 连接未释放 调pool配置 §7.2

十、何时该升级/寻求帮助

╔═══════════════════════════════════════════════════════════╗
║         问题升级决策树                                     ║
╠═══════════════════════════════════════════════════════════╣
║                                                           ║
║  自己能解决?                                              ║
│  ├── 是 → 按照本文档操作                                   │
│  │                                                          │
│  └── 否 ↓                                                  │
║                                                            ║
║  社区有人遇到过?                                          │
│  ├── 是 → GitHub Issues / Discord / 论坛搜索               │
│  │                                                          │
│  └── 否 ↓                                                  │
║                                                            ║
║  影响范围?                                                 │
│  ├── 个人使用 → 提GitHub Issue(附诊断日志)                │
│  ├── 团队受影响 → 企业版支持工单                            │
│  └── 生产事故 → 立即电话支持 + 启动应急预案                │
║                                                            ║
║  🔧 报问题时请务必包含:                                    │
║  1. monkeycode --version                                  │
║  2. 操作系统和GPU型号                                      │
║  3. 完整的错误日志(不是截图!)                           │
║  4. 复现步骤                                              │
║  5. 已尝试过的解决方法                                    │
║                                                            ║
╚═══════════════════════════════════════════════════════════╝

总结

好的故障排查能力 = 结构化的思维 + 丰富的经验 + 完善的工具链

本文覆盖的核心能力:

  1. 快速定位:决策树帮你第一时间缩小排查范围
  2. 系统化诊断:从连接→性能→质量→插件→GPU全面覆盖
  3. 即用脚本:一键诊断、OOM应急、日志分析——复制就能用
  4. 标本兼治:不仅告诉你怎么修,还告诉你怎么预防
  5. 知道何时求助:解决问题的成本 vs 寻求帮助的成本

一句话总结收藏这篇手册,下次出问题时它能帮你节省数小时的排查时间。


下一篇预告:《MonkeyCode版本演进历程:从v1.0到v4.0的技术跨越》

posted on 2026-06-22 12:25  MonkeyCode  阅读(0)  评论(0)    收藏  举报