前言
OpenClaw 基于 Node.js 运行,默认情况下 V8 引擎的堆内存上限约为 1.5GB(64位系统)。当你发现 OpenClaw 进程内存持续增长,甚至导致系统卡顿或 OOM(Out of Memory)被杀时,本文的排查方法将帮助你找到原因并解决问题。
一、快速判断内存状态
1.1 查看当前内存使用
# 方法一:通过 OpenClaw 健康端点
curl -s http://localhost:18789/health/detail | jq '.memory'
# 返回示例:
# {
# "heapUsed": "185MB",
# "heapTotal": "256MB",
# "rss": "310MB",
# "external": "12MB"
# }
# 方法二:直接查看进程内存
ps aux | grep openclaw | grep -v grep
# 方法三:使用 top/htop 实时查看
top -p $(pgrep -f "openclaw up")
1.2 内存指标含义
| 指标 | 含义 | 正常范围 |
|---|---|---|
| RSS | 实际物理内存占用 | < 500MB |
| Heap Used | V8 堆已使用量 | < 300MB |
| Heap Total | V8 堆总分配量 | < 512MB |
| External | C++ 对象内存 | < 50MB |
如果 Heap Used 持续增长且不回落,很可能存在内存泄漏。
二、Node.js 内存限制配置
2.1 设置最大堆内存
# 方法一:通过环境变量设置
export NODE_OPTIONS="--max-old-space-size=512"
openclaw restart
# 方法二:在配置文件中设置(PM2 方式)
# ecosystem.config.js
{
env: {
NODE_OPTIONS: "--max-old-space-size=512"
}
}
# 方法三:Systemd 方式
# /etc/systemd/system/openclaw.service
# Environment=NODE_OPTIONS=--max-old-space-size=512
推荐的内存限制设置:
| 服务器内存 | 建议 max-old-space-size | 说明 |
|---|---|---|
| 512MB | 256 | 低配 VPS,需精简配置 |
| 1GB | 384 | 入门级,支持 2-3 个频道 |
| 2GB | 512 | 标准配置 |
| 4GB+ | 1024 | 充足,适合多频道高并发 |
2.2 启用垃圾回收优化
# 暴露 GC,允许手动触发
export NODE_OPTIONS="--max-old-space-size=512 --expose-gc"
# 更积极的 GC 策略(降低内存但略影响性能)
export NODE_OPTIONS="--max-old-space-size=512 --gc-interval=100"
三、对话历史清理
对话历史是内存增长的主要原因之一。每个活跃对话都会在内存中保留上下文。
3.1 配置对话上下文限制
// ~/.config/openclaw/openclaw.json5
{
"conversation": {
// 每个对话保留的最大消息数
"maxMessages": 50,
// 对话空闲超时(秒),超时后清理内存
"idleTimeout": 1800,
// 最大并发对话数
"maxConcurrent": 100,
// 上下文窗口策略:sliding(滑动窗口) 或 summarize(摘要)
"contextStrategy": "sliding"
}
}
3.2 手动清理对话缓存
# 通过 API 清理所有非活跃对话
curl -X POST http://localhost:18789/admin/cleanup \
-H "Content-Type: application/json" \
-d '{"type": "conversations", "olderThan": "1h"}'
# 重启服务(会清空所有内存中的对话)
openclaw restart
3.3 定期自动清理
# 创建定时清理脚本
cat > /usr/local/bin/openclaw-cleanup.sh << 'EOF'
#!/bin/bash
curl -sf -X POST http://localhost:18789/admin/cleanup \
-H "Content-Type: application/json" \
-d '{"type": "conversations", "olderThan": "2h"}'
echo "[$(date)] 对话缓存清理完成" >> /var/log/openclaw-cleanup.log
EOF
chmod +x /usr/local/bin/openclaw-cleanup.sh
# 每小时执行一次
echo "0 * * * * /usr/local/bin/openclaw-cleanup.sh" | crontab -
四、内存泄漏检测
4.1 使用 Node.js 内置诊断
# 启动时开启堆快照功能
export NODE_OPTIONS="--max-old-space-size=512 --heapsnapshot-signal=SIGUSR2"
openclaw restart
# 在内存增长时生成堆快照
kill -USR2 $(pgrep -f "openclaw up")
# 快照文件会生成在工作目录,可用 Chrome DevTools 分析
# 打开 Chrome -> F12 -> Memory -> Load 快照文件
4.2 监控内存增长趋势
#!/bin/bash
# 保存为 memory-monitor.sh
# 每分钟记录一次内存使用,用于分析趋势
LOG_FILE="/var/log/openclaw-memory.csv"
# 写入表头
if [ ! -f "$LOG_FILE" ]; then
echo "timestamp,rss_kb,heap_used,heap_total" > "$LOG_FILE"
fi
while true; do
TIMESTAMP=$(date +%Y-%m-%dT%H:%M:%S)
RSS=$(ps -o rss= -p $(pgrep -f "openclaw up") 2>/dev/null)
HEALTH=$(curl -sf http://localhost:18789/health/detail 2>/dev/null)
if [ -n "$RSS" ] && [ -n "$HEALTH" ]; then
HEAP_USED=$(echo "$HEALTH" | jq -r '.memory.heapUsed')
HEAP_TOTAL=$(echo "$HEALTH" | jq -r '.memory.heapTotal')
echo "$TIMESTAMP,$RSS,$HEAP_USED,$HEAP_TOTAL" >> "$LOG_FILE"
fi
sleep 60
done
4.3 识别内存泄漏的特征
通过分析上述日志,判断是否存在内存泄漏:
- 正常行为:内存在 GC 后能回到稳定水位,呈锯齿状波动
- 内存泄漏:内存持续上升,GC 后的基线也在不断升高
- 一次性增长:加载大量技能或连接多个频道时一次性增长,之后稳定
五、堆快照分析
5.1 生成堆快照
# 方法一:通过信号触发
kill -USR2 $(pgrep -f "openclaw up")
# 快照文件生成在当前工作目录
# 方法二:使用 v8-profiler(需要代码层面支持)
# 一般在开发调试时使用
5.2 使用 Chrome DevTools 分析
- 打开 Chrome 浏览器
- 地址栏输入
chrome://inspect - 点击 "Open dedicated DevTools for Node"
- 切换到 Memory 标签页
- 加载
.heapsnapshot文件 - 按 "Retained Size" 排序,找到占用最多内存的对象
5.3 常见内存泄漏源
| 泄漏源 | 表现 | 解决方法 |
|---|---|---|
| 未清理的事件监听器 | EventEmitter 对象增长 | 确保 removeListener |
| 全局缓存无上限 | Map/Object 持续增长 | 设置缓存上限和 LRU 策略 |
| 未关闭的 WebSocket | Socket 对象累积 | 检查断连清理逻辑 |
| 大型对话上下文 | String 对象占用大 | 限制上下文长度 |
| 技能插件泄漏 | 第三方代码问题 | 逐个禁用排查 |
六、低内存设备优化
如果你在树莓派、低配 VPS 等内存受限的设备上运行 OpenClaw,以下配置可以显著降低内存使用。
6.1 精简配置
// ~/.config/openclaw/openclaw.json5 - 低内存优化版
{
"conversation": {
"maxMessages": 20,
"idleTimeout": 600,
"maxConcurrent": 20,
"contextStrategy": "sliding"
},
"skills": {
// 只加载必要的技能
"autoLoad": false,
"whitelist": ["basic-chat"]
},
"channels": {
// 只启用必要的频道
},
"cache": {
"maxSize": "50MB"
}
}
6.2 使用 Swap 作为缓冲
# 创建 1GB swap 文件
sudo fallocate -l 1G /swapfile
sudo chmod 600 /swapfile
sudo mkswap /swapfile
sudo swapon /swapfile
# 永久生效
echo '/swapfile none swap sw 0 0' | sudo tee -a /etc/fstab
# 调整 swappiness(降低为10,优先使用物理内存)
echo 'vm.swappiness=10' | sudo tee -a /etc/sysctl.conf
sudo sysctl -p
6.3 使用轻量模型
选择较小的模型可以减少上下文处理的内存开销:
{
"models": {
"primary": {
"provider": "ollama",
"model": "phi3:mini" // 约 2GB 显存/内存
}
}
}
七、PM2 内存限制自动重启
利用 PM2 的内存限制功能,在内存超标时自动重启:
// ecosystem.config.js
module.exports = {
apps: [{
name: "openclaw",
script: "openclaw",
args: "up",
max_memory_restart: "400M",
env: {
NODE_OPTIONS: "--max-old-space-size=512"
}
}]
};
# 应用配置
pm2 start ecosystem.config.js
# 查看内存使用和重启次数
pm2 describe openclaw | grep -E "memory|restart"
八、内存问题排查流程图
内存过高
│
├── RSS > 500MB?
│ ├── 是 → 检查 Heap Used
│ │ ├── Heap Used 持续增长 → 内存泄漏
│ │ │ ├── 生成堆快照分析
│ │ │ ├── 逐个禁用技能排查
│ │ │ └── 检查对话上下文限制
│ │ └── Heap Used 稳定 → External 内存
│ │ └── 检查 MCP Server 或原生模块
│ └── 否 → 属于正常范围
│
└── 被 OOM Killer 杀死?
├── 增加 swap 空间
├── 设置 --max-old-space-size
├── 减少并发对话数
└── 升级服务器内存
通过以上方法,你应该能够诊断并解决大多数 OpenClaw 内存相关的问题。如果内存泄漏持续存在,建议在 OpenClaw 的 GitHub 仓库提交 Issue,附上堆快照分析结果。