1. 问题现象与背景
最近在迁移OpenClaw的vLLM推理服务时遇到了一个棘手的问题。原本运行在10.10.85.220服务器上的vLLM服务需要迁移到新的192.168.1.221服务器上。按照常规操作,我修改了全局配置文件~/.openclaw/openclaw.json中的baseUrl参数,并重启了gateway服务。然而,之后所有的请求都返回了Connection error错误,gateway日志中持续输出"embedded run agent end: isError=true error=Connection error."这样的警告信息。
这种情况特别令人困惑,因为:
- 通过curl和Node.js直接测试新服务器的vLLM接口都能正常响应
- gateway服务状态检查显示一切正常
- 网络连通性测试也没有发现问题
2. 详细排查过程
2.1 基础环境检查
首先确认gateway服务状态:
bash复制openclaw gateway status
输出显示gateway运行正常,RPC探测通过,监听地址正确。这排除了gateway本身的问题。
接着测试vLLM服务的可达性:
bash复制curl http://192.168.1.221:8000/v1/models
这个命令成功返回了模型列表,证明vLLM服务确实在新服务器上正常运行。
2.2 深入网络层分析
为了排除curl测试与OpenClaw实际请求之间的差异,我用Node.js编写了一个简单的测试脚本:
javascript复制const http = require('http');
const req = http.request({
hostname: '192.168.1.221',
port: 8000,
path: '/v1/completions',
method: 'POST',
headers: {'Content-Type': 'application/json'}
}, res => { res.on('data', c => console.log(c.toString())); });
req.write(JSON.stringify({model:'gpt-oss-120b', prompt:'hi', max_tokens:5}));
req.end();
这个测试也成功了,说明从运行环境到网络层面都没有问题。
2.3 系统调用追踪
为了找出问题根源,我决定使用strace追踪gateway进程的系统调用:
bash复制PID=$(pgrep -f "openclaw.*gateway")
strace -p $PID -e trace=network -f 2>&1 | grep -E "connect|192.168" &
sleep 10; kill %1
这个命令运行10秒后,发现了一个关键现象:完全没有到192.168.1.221:8000的TCP连接尝试!所有的网络活动都是mDNS(5353端口)流量。这说明OpenClaw根本没有尝试向vLLM服务发起HTTP请求,请求在本地就被拦截了。
2.4 配置文件检查
根据这个发现,我检查了provider状态:
bash复制openclaw models status
输出中有一行特别值得注意:
code复制source=models.json: ~/.openclaw/agents/main/agent/models.json
查看这个文件:
bash复制cat ~/.openclaw/agents/main/agent/models.json
果然发现了问题:
json复制{
"providers": {
"vllm": {
"baseUrl": "http://10.10.85.220:8000/v1", // 旧IP!
...
}
}
}
3. 问题根源分析
3.1 配置文件优先级机制
OpenClaw采用了多层配置文件的设计,优先级从高到低如下:
| 配置文件 | 路径 | 说明 |
|---|---|---|
| models.json | ~/.openclaw/agents/main/agent/models.json | 最高优先级,agent级别模型配置 |
| auth-profiles.json | ~/.openclaw/agents/main/agent/auth-profiles.json | 认证信息 |
| openclaw.json | ~/.openclaw/openclaw.json | 全局配置 |
当只修改openclaw.json时,models.json中的旧配置仍然会覆盖全局配置。
3.2 Cooldown保护机制
OpenClaw内置了一个保护机制:当某个provider连续请求失败多次后,会临时屏蔽对该provider的所有请求。这表现为请求根本不发出,直接返回Connection error。虽然这是一种合理的保护机制,但在排查问题时容易误导方向。
4. 解决方案
4.1 直接修改models.json(推荐)
bash复制# 将旧IP替换为新IP
sed -i 's/10.10.85.220/192.168.1.221/g' \
~/.openclaw/agents/main/agent/models.json
# 确认修改
grep baseUrl ~/.openclaw/agents/main/agent/models.json
# 重启gateway清除cooldown状态
openclaw gateway restart
4.2 批量更新所有配置文件
如果是完整的服务器迁移,建议检查并更新所有相关配置文件:
bash复制# 全局搜索旧IP
grep -r "10.10.85.220" ~/.openclaw/
# 批量替换
find ~/.openclaw/ -name "*.json" -exec \
sed -i 's/10.10.85.220/192.168.1.221/g' {} \;
openclaw gateway restart
4.3 仅重置Cooldown状态
如果只是想临时解除保护状态而不修改配置:
bash复制openclaw models status --reset-cooldown
# 或直接重启gateway
openclaw gateway restart
5. 验证修复
重启后观察日志:
bash复制openclaw logs --follow 2>&1 | grep -E "agent end|agent start"
正常输出应该类似:
code复制debug agent/embedded embedded run agent start: runId=xxx
info agent/embedded embedded run agent end: runId=xxx isError=false
6. 预防建议
-
迁移服务器时,除了修改openclaw.json外,必须检查:
- ~/.openclaw/agents/main/agent/models.json
- ~/.openclaw/agents/*/agent/models.json(多agent场景)
-
使用官方命令修改配置,避免直接编辑文件可能导致的遗漏:
bash复制openclaw config set models.providers.vllm.baseUrl http://192.168.1.221:8000/v1这个命令会自动更新所有相关配置文件。
-
排查Connection error的顺序:
- 检查gateway状态
- 直接测试vLLM接口
- 查看provider状态和配置来源
- 检查source字段指向的配置文件
7. 经验总结
在实际操作中,我总结了以下关键点:
-
OpenClaw的配置文件有明确的优先级,修改配置时要确认最终生效的是哪个文件。
-
Cooldown机制虽然保护了系统,但也增加了排查难度。遇到Connection error时,要首先考虑是否触发了保护机制。
-
使用strace等系统工具可以快速定位问题是否出在网络层面。
-
官方提供的config set命令比直接编辑文件更可靠,能确保所有相关配置同步更新。
-
在复杂的系统中,看似简单的配置变更可能会涉及多个层面的联动,需要全面考虑。
这个问题虽然最终解决起来很简单,但排查过程却相当曲折。希望通过分享这个案例,能帮助其他开发者避免类似的困扰。在配置变更时,一定要全面考虑系统各个组件的相互关系,不能只关注最明显的配置项。