Skip to content

流量

WireGuard 吞吐数据。该子系统横跨三层,本页覆盖其全部落点:

落点分辨率覆盖窗口用途
Redis traffic:window:<node>L530 s2 h实时吞吐视图
node_traffic_rollupL35 min60 天节点级趋势与「上期对比」
node_iface_traffic_rollupL35 min60 天按对端 AS 划分流量
node_traffic_last_sample / node_iface_traffic_lastL2当下速率差分的持久基准

采用三层而非单层的原因:agent 上报的是累计字节,速率必须由相邻两次采样差分得出。热窗口置于 Redis(快,可丢失),存档置于 PostgreSQL(慢,不可重建),而差分基准为两者共同所需——因此它单独落 PostgreSQL,以保证 Redis 不可用时 5 min 存档仍可正常累加。

模型定义在 app/db/models/traffic.py,通用桶形态与保留期见时序建模通则


数据流

节点级走 30 s 轻量上报,接口级走 5 min 快照,两条路径节奏不同而形态一致。

提示: Redis 不可用时 TrafficStore 改读 node_traffic_last_sample 完成差分,5 分钟存档不会断档,仅实时视图出现空窗。这条回退路径正是热窗口得以留在可丢弃的 L5 的前提。


node_traffic_rollup

每节点每 5 min 桶的 WG 吞吐速率降采样,随采样 upsert(累加进桶)。

类型约束 / 默认说明
node_idString(64)PK(复合),FK→nodes.node_id(CASCADE)所属节点
bucket_startBigIntegerPK(复合)桶起点(epoch 秒,对齐 5 min)
rx_rate_sum / tx_rate_sumFloatNOT NULL,默认 0.0落进该桶的各次瞬时速率(字节/秒)之和;读时以 sum / count 得均值
sample_countIntegerNOT NULL,默认 0采样次数
updated_atDateTime(tz)server_default now,带 onupdate更新时刻

一个 5 min 桶会被 30 s 采样 upsert 约 10 次——这是全库写放大最明显的一处,也是它成为唯一死元组稳定偏高的表的原因(实测约 7 900)。它同时是分区化的三张目标表之一,但注意分区只消除裁剪产生的死元组,消除不了 upsert 产生的。

node_traffic_last_sample

每节点最近一次累计采样,速率差分的持久 prev。

类型约束 / 默认说明
node_idString(64)PK,FK→nodes.node_id(CASCADE)主键即外键
captured_atString(64)NOT NULL采样时刻(ISO 8601,与 Redis 热窗口元素同形)
rx_bytes / tx_bytesBigIntegerNOT NULL,默认 0全 peer 累计收 / 发字节
updated_atDateTime(tz)server_default now,带 onupdate更新时刻

node_iface_traffic_rollup

按 (节点, WG 接口) 粒度的 5 min 速率存档,是「按对端 AS 划分流量」的数据层。

类型约束 / 默认说明
node_idString(64)PK(复合),FK→nodes.node_id(CASCADE)所属节点
interfaceString(64)PK(复合)WG 接口名
bucket_startBigIntegerPK(复合)桶起点
rx_rate_sum / tx_rate_sumFloatNOT NULL,默认 0.0速率之和
sample_countIntegerNOT NULL,默认 0采样次数
updated_atDateTime(tz)server_default now,带 onupdate更新时刻

全库最大的时序表(实测 777 120 行 / 127 MB)。增长维度是「节点数 × 接口数」,而接口数随对等关系增长——这是全库增长最快的一条曲线,且增速由对等业务量而非运维决定,见增长维度

旧 agent(< 1.0.143)的快照不带 per-peer 计数时整个调用 no-op。

node_iface_traffic_last

按 (节点, 接口) 的差分 prev,列同 node_traffic_last_sample,主键为复合 (node_id, interface)