OpenClaw 监控站点优化笔记

五一假期回来第一件事,把博客的监控页面优化了一下。记录一下排查过程和改了什么。

背景

博客用 OpenClaw 作为 AI Agent,用 Flask 写了一个监控面板(CPU、内存、Swap、磁盘、OpenClaw 会话等),挂在 monitor.kakarotzz.site。五一前服务器负载一直偏高,但没仔细排查。

问题发现

上来先看服务器负载:

1
2
3
uptime          # load average: 0.40, 0.51, 0.38
free -h # Mem: 4.2Gi / 7.5Gi, Swap: 3.9Gi / 9.9Gi
ps aux --sort=-%cpu | head -10

结果让人意外:罪魁祸首不是服务器本身负载高,而是 12 个 headless Chrome 进程

进程 CPU 内存
Chrome (renderer) × 6 累计 ~47% ~1.4GB
Chrome (gpu/utility) ~7% ~200MB

这些 Chrome 是 OpenClaw 的 browser tool 跑起来的。问题是我们根本没用这个功能。

解决 Chrome 资源占用

修改 OpenClaw 配置,三处都要关:

1
2
3
4
# /root/.openclaw/openclaw.json
cfg['agents']['defaults']['sandbox']['browser']['enabled'] = False # agent 级别
cfg['browser']['enabled'] = False # 顶层
cfg['plugins']['entries']['browser']['enabled'] = False # plugin 级别

改完之后 kill 掉所有残留进程:

1
sudo kill -9 $(ps aux | grep '[c]hrome' | awk '{print $2}')

效果吹糠见米:

指标 优化前 优化后
内存使用 4.2 GB 1.7 GB
Swap 使用 3.9 GB 146 MB

Flask API 优化

Flask 监控后端原来每个前端页面加载要同时发 4 个 XHR 请求: /api/system/api/openclaw/api/usage/api/nodes。其中 nodes 接口每次都会 subprocess.run(['pnpm', 'openclaw', 'nodes', 'status']) 调子进程,overhead 很大。

1. 新增 /api/all 合并接口

一次请求返回 system + openclaw 数据,减少 HTTP 开销:

1
2
3
4
5
6
7
@app.route('/api/all')
def api_all():
return jsonify({
"timestamp": now.isoformat(),
"system": { ... },
"openclaw": openclaw_status(),
})

2. Nodes 结果 30 秒缓存

用线程锁 + 时间戳实现简单缓存,避免每次请求都调子进程:

1
2
3
4
5
6
7
8
9
_nodes_cache = {"data": [], "ts": 0}
_nodes_lock = threading.Lock()

def _get_cached_nodes():
global _nodes_cache
with _nodes_lock:
if time.time() - _nodes_cache["ts"] < 30:
return _nodes_cache["data"]
# ... fetch and cache

3. CPU 采样时间优化

psutil.cpu_percent(interval=0.5) 改为 interval=0.3,减少阻塞时间。


Nginx 层优化

/api/ 加上缓存策略,减少对 Flask 的穿透:

1
2
3
4
5
location /api/ {
proxy_pass http://127.0.0.1:5000/api/;
proxy_cache_valid 200 10s;
add_header X-Cache-Status $upstream_cache_status always;
}

Nodes 接口在 Flask 层已经做了 30 秒缓存,nginx 这层不需要额外 conditional cache。


前端优化

刷新频率:5s → 15s

原来 5 秒轮询一次,API 调用频繁。改成 15 秒,足够监控需求。

懒加载 Usage 和 Nodes

首屏只加载 /api/all,Usage 和 Nodes 数据在页面加载完后再异步请求,不阻塞首屏渲染:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
async function fetchAll() {
const res = await fetch('/api/all');
const data = await res.json();
renderSystem({timestamp: data.timestamp, ...data.system});
renderOpenClaw({status: data.openclaw});

// 懒加载
if (!window._usageLoaded) {
window._usageLoaded = true;
fetch('/api/usage').then(r => r.json()).then(d => renderUsage(d));
fetch('/api/nodes').then(r => r.json()).then(d => renderNodes(d));
}
}
setInterval(fetchAll, 15000);

总结

这次优化核心就三点:

  1. 关掉没用的 Chrome 进程 — 内存从 4.2GB 降到 1.7GB,立竿见影
  2. 合并 API + 加缓存 — 减少 HTTP 请求数和后端计算量
  3. 降低前端轮询频率 — 从 5 秒改到 15 秒

服务器负载从”看起来还行”变成了”真的没什么负载”,Swap 使用量从 3.9GB 降到 146MB,内存充足。

如果你也有 OpenClaw 部署,建议确认一下 browser tool 是不是真的在用,没用到就关掉,能省出大量资源。