
一台服务器上运行 60 个容器
一个裸金属服务器运行数十到数百个 Hoody 容器。KSM 和 BTRFS 去重使边际成本接近零。
二十个 agent 用 curl -T 把指标推到一个管道 URL。你的仪表盘用 ?progress 读同一个 URL,把 SSE 流直接渲染进页面。无 InfluxDB、无 Prometheus、无抓取间隔。只是一根线。
无 Prometheus、无 InfluxDB、无指标服务——只是一条管道上的 SSE
每个 agent 把它那一行 curl 进同一条管道路径。仪表盘的浏览器在那条路径上以 ?progress 打开一个 EventSource。Hoody Pipe 服务器什么都不存——一端到达的字节从另一端离开。
#!/bin/sh
# Agent monitor loop — one line per second.
while true; do
cpu=$(top -bn1 | awk '/Cpu/ [print $2]')
mem=$(free | awk '/Mem:/ [printf "%.0f", $3/$2*100]')
line="cpu=$cpu mem=$mem qps=$(cat /tmp/qps) ts=$(date +%s)"
echo "$line" | curl -T - https://pipe.hoody.com/api/v1/pipe/metrics-$AGENT_ID
sleep 1
done// One <script> in one HTML file. No backend.
const tiles = document.querySelectorAll('[data-agent]');
tiles.forEach((tile) => [
const id = tile.dataset.agent;
// ?progress turns the pipe path into an SSE stream.
const sse = new EventSource(
`https://pipe.hoody.com/api/v1/pipe/metrics-$[id]?progress`,
);
sse.addEventListener('metric', (e) => [
const [ cpu, mem, qps ] = JSON.parse(e.data);
tile.querySelector('.cpu').textContent = `$[cpu]%`;
tile.querySelector('.mem').textContent = `$[mem]%`;
tile.querySelector('.qps').textContent = qps;
]);
]);agent 在 curl。浏览器在 EventSource。管道在转发。两者之间没有任何东西要扩容、重启或买单。关掉仪表盘,流就结束。再打开它,一秒之内你又看到实时数据。
你删掉后端所放弃的,会以更简单的形式还回来。
没有抓取间隔要等。agent 最后一次写就是仪表盘当前这一帧。管道直接转发——没有中间刷盘。
无保留策略,因为无存储。无磁盘可填满、无压缩窗口、无时间序列索引可损坏。指标只在有人看的时候存在。
仪表盘是一份你能托管在任何地方——或从磁盘打开——的 HTML 文件。无 agent 要装、无守护进程要跑、无 DataDog 席位要开。管道 URL 就是整个堆栈。
标准的 agent 到仪表盘堆栈有四个活动部件。管道模型有零个。同一根线,半屏 curl。
当你跳过数据库时,那些你以前要管理的东西就不再存在。一根线上没有保留策略。
一条管道路径是一小块但真实的基础设施。数字来自 Hoody Pipe API 的保证,不是杜撰的基准。
最多 256 个仪表盘或 curl tail 可以用 ?n 订阅同一路径。最慢的读取者反压自己,但永远不阻塞其他人。
每条路径最多 50 个 ?progress SSE 查看者。他们不占用接收者槽位——你的仪表盘标签页和你的终端可以并行观看。
服务器不写磁盘。发送端到达的字节从读取端离开。两者之间没有刷盘窗口。
限制依据 Hoody Pipe API:接收者数量 1–256,每条路径 progress 旁观者上限 50,progress 连接 TTL 30 分钟,传输后驻留 30 秒。
仪表盘没去查数据库。字节就那样到了。
当你想要一块指标仪表盘时会去拿的标准工具。每一种都向你收一份数据库和一个守护进程的钱。管道两个都不收。
别再抓取。别再存储。看这根线——你不看的时候,线是空的。