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
# 期望: 200echo "\n=== API服务层 ==="
curl -s -o /dev/null -w "%{http_code}" http://localhost:8080/api/v1/health
# 期望: 200echo "\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 timedef 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() - startprint(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" ]; thenecho "PID: $pid"cat /proc/$pid/status | grep VmRSSecho "观察该值是否持续增长"
fiecho ""
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/ZGC2. 调整GC参数: -XX:MaxGCPauseMillis=2003. 监控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/lowcategory: strdescription: strline_number: intpattern: strSECURITY_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 requestsdef 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 torchif torch.cuda.is_available():torch.cuda.empty_cache()print(f"✅ 已清理CUDA缓存,释放显存")# 4. 降低batch sizerequests.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" ]; thenecho "❌ 目录不存在: $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[@]}"; doif [ -f "$MODEL_DIR/$f" ]; thenecho "✅ $f"elseecho "❌ 缺少: $f"fi
doneecho ""
echo "[3] 检查模型权重文件..."
if [ -f "$MODEL_DIR/model.safetensors.index.json" ]; thenecho "找到分片索引,检查分片完整性..."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 osexists = 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" ]; thenecho "✅ 单文件权重存在"
elseecho "❌ 未找到任何权重文件!"
fiecho ""
echo "[4] 检查文件完整性(SHA256)..."
if [ -f "$MODEL_DIR/checksum.sha256" ]; thencd "$MODEL_DIR"sha256sum -c checksum.sha256
elseecho "⚠️ 无校验文件,跳过完整性检查"
fiecho ""
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 # InfiniBandethtool -i eth0 # 以太网
fiecho ""
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 pool 或 Connection pool exhausted
修复:
# monkeycode redis 配置优化
redis:host: "redis-cluster.internal"port: 6379mode: "cluster" # 或 standalone/sentinelconnection_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 pipefailRED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'PASS=0
WARN=0
FAIL=0check() {local label="$1"local condition="$2"local severity="${3:-FAIL}"if eval "$condition" > /dev/null 2>&1; thenecho -e "${GREEN}✅ ${label}${NC}"((PASS++))elseif [ "$severity" = "WARN" ]; thenecho -e "${YELLOW}⚠️ ${label}${NC}"((WARN++))elseecho -e "${RED}❌ ${label}${NC}"((FAIL++))fifi
}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; thenGPU_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" WARNGPU_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" WARNinfo "GPU显存: ${GPU_MEM_USED}MB / ${GPU_MEM_TOTAL}MB (${GPU_MEM_PCT}%)"info "GPU最高温度: ${GPU_TEMP}°C"
elseecho -e "${YELLOW}⚠️ 未检测到nvidia-smi(可能无GPU或驱动未安装)${NC}"((WARN++))
fi# ===== Docker/K8s =====
echo ""
echo "━━━ 容器运行时 ━━━"if command -v docker &> /dev/null; thencheck "Docker服务运行中" "docker info > /dev/null 2>&1"MC_CONTAINER=$(docker ps --filter "name=monkeycode" --format "{{.Names}}" | head -1)if [ -n "$MC_CONTAINER" ]; theninfo "容器名称: $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" WARNif [ "$RESTART_COUNT" -gt 0 ]; theninfo "⚠️ 容器已重启 $RESTART_COUNT 次"info "最近退出码: $(docker inspect -f '{{.State.ExitCode}}' $MC_CONTAINER)"fielseecho -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" != "{}" ]; thencheck "API服务健康端点正常" "true"echo "$HEALTH_RESP" | python3 -m json.tool 2>/dev/null || echo "$HEALTH_RESP"
elseecho -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 ]; thenecho ""echo -e "${RED}🔴 发现 ${FAIL} 个严重问题,请按上述提示逐一修复${NC}"exit 1
elif [ "$WARN" -gt 0 ]; thenecho ""echo -e "${YELLOW}🟡 发现 ${WARN} 个警告项,建议尽快处理${NC}"exit 0
elseecho ""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. 已尝试过的解决方法 │
║ ║
╚═══════════════════════════════════════════════════════════╝
总结
好的故障排查能力 = 结构化的思维 + 丰富的经验 + 完善的工具链
本文覆盖的核心能力:
- 快速定位:决策树帮你第一时间缩小排查范围
- 系统化诊断:从连接→性能→质量→插件→GPU全面覆盖
- 即用脚本:一键诊断、OOM应急、日志分析——复制就能用
- 标本兼治:不仅告诉你怎么修,还告诉你怎么预防
- 知道何时求助:解决问题的成本 vs 寻求帮助的成本
一句话总结:收藏这篇手册,下次出问题时它能帮你节省数小时的排查时间。
下一篇预告:《MonkeyCode版本演进历程:从v1.0到v4.0的技术跨越》
