网络统计
管理面板中的 Network 视图是对中继实际发送内容的实时细分。要回答“我的模组在网络上花了多少代价”,它是最快的途径,所以在你发布一个每 tick 都同步的组件之前,值得先学会怎么看这一页。
查看它需要 Dashboard access 权限。
采样方式
服务器每秒关闭一个测量窗口,并通过事件流推送到面板。它保留最近 300 个窗口;图表和表格显示最近的 120 个,这就是 LIVE 标记旁 last 120s 标签的含义。
窗口之间不重叠,也不会跨窗口做平滑。每个计数器都在窗口边界处被取样并清零。因此一次流量突发会一直留在汇总数据里,直到它从 120 个窗口的视图末端滑出,然后自行消失。这是正常现象,不是统计被重置了。
只有在连续五秒没有收到样本之后,数据流才会被报告为中断。连接断开会自行重试,服务器在重连时会重放它保留的历史,所以短暂中断不会在图表上留下缺口。
线路字节与负载字节
关于这一页几乎所有的困惑,都来自把两个计量层混为一谈,而它们是刻意分开的,永远不会相等。
线路(Wire) 是来自 LiteNetLib 的真实数据:它实际写入套接字的每一个字节,包括通道头、确认包、心跳和可靠重传。Ingress、Egress 和 UDP 吞吐量这几个数字都基于它。
负载(Payload) 只统计应用层字节,在服务器组装和解析数据包的位置计数。按组件和按消息类型的表格显示的就是它,而它也是唯一能把字节归因到你的模组的那一层。
负载的总和永远小于线路。二者之差就是 Protocol overhead 这块指标,它本身也是有用的信号:差距大意味着开销来自确认包和重传,而不是你的数据。
两个层都不统计每个数据报都要携带的 28 字节 IP 与 UDP 头。Link egress 把它们加了回来,也只有这个数字才反映你的主机实际计费的量。
出站流量按收件人计数。一份增量组装一次、转发给五个对端,就是五倍的出站流量,因为那才是真正离开机器的量。这也是为什么对于任何要同步给繁忙区域的数据,扇出比负载大小更重要。
汇总指标块
| 指标块 | 含义 |
|---|---|
| Ingress | 每秒接收的线路字节数,下方是每秒数据包数。仅最新窗口。 |
| Egress | 每秒发送的线路字节数,下方是每秒数据包数。仅最新窗口。 |
| Connected peers | LiteNetLib 当前保持连接的对端数量。 |
| Server tick p99 | 最新窗口内 tick 耗时的 99 分位值,下方是实际达到的网络循环频率。 |
| Protocol overhead | 线路出站减去负载出站,以速率表示。只有当窗口内负载超过 16 KB 时才显示占出站流量的百分比,否则会直接说明原因,而不是基于一个接近零的分母给出一个看似确定的数字。 |
| Link egress | 线路出站加上每个数据报 28 字节。大量小包在负载上很便宜,在这里却很贵。 |
UDP 吞吐量
每秒进出的线路字节数,每个窗口一个点。不含 IP 与 UDP 头,所以请把它与 Link egress 比较,而不是与主机的带宽图表比较。
服务器 tick 耗时
一次服务器 tick 耗时的 p50 和 p99,测量范围覆盖整个系统根更新。你的服务器模组注册的系统就运行在其中,所以某个系统每 tick 做得太多,最先会在这张图上显现。
耗时按 1 微秒的桶做直方图统计,所以分位值是精确的,而不是插值得出的。超过 20 毫秒的都会归入最高的桶;如果你看到一条平在 20 毫秒的直线,那么真实值比它更差。
p99 上升而 p50 平稳,通常是某个系统偶尔要做重活的典型形状,例如一个用定时器扫描全部实体、而不是对变化作出反应的系统。
出站流量最高的组件
负载出站速率最高的八个组件。低于这八个的会被合并成一行 Other (n) 而不是被丢弃,所以这些条形始终能对上完整的总量。
坐标轴标签会去掉末尾的 Component 后缀以节省宽度,所以 MonsterAnimationComponent 在图上显示为 MonsterAnimation。下方表格保留完整名称。
按 ECS 组件的流量
按组件统计的负载,在可见窗口范围内汇总。这里的名称就是内置原型上的组件类型,以及你的模组注册的任何组件。
| 列 | 含义 |
|---|---|
| Component | 组件的类型名。 |
| In / Out | 每秒负载字节数,在整个可见窗口上取平均。 |
| In msgs / Out msgs | 消息数量。与旁边的字节列不同,这两列是窗口内的总数,不是速率。 |
| In/msg / Out/msg | 每条消息的平均负载字节数。 |
| Fan-out | 出站除以入站,基于汇总值。表示一次客户端更新会扩散多远。 |
每一行都除以同一个窗口总时长,所以一次性的加入负载会报告为一个较小的每秒数值,而不会看起来像持续负载。各行之间本就是可以互相比较的。
某个“每条消息”列上出现黄色 !,表示平均负载小于每个数据报所需的 28 字节封装开销,也就是说链路开销的大部分是包头而不是数据。解决办法是每个包里多带一些状态,而不是继续压缩负载。
Fan-out 显示 - 表示该组件在窗口内完全没有入站流量。那是未定义,而不是零,对于客户端从不发送、由服务器写入的组件来说,这正是预期的读数。凡是服务器端系统写入的组件都属于这一类。
排序标签(total、egress、ingress、fan-out)只会重新排列各行。扇出未定义的组件会排在最后,而不是当作零处理。
按消息类型的流量
同样是那些负载字节,但按线路消息编码而不是按组件分组。用它来区分 ECS 状态同步、RPC 和一次性事件。
内置编码会以其协议名称显示:EcsDelta、EcsSnapshot、EcsCreateEntity、EcsDeleteEntity、EcsChangeOwnership、AreaEvent、HandshakeConnected 等等。自定义 RPC 编码没有可查的名称,会显示为 ServerRpc(n) 和 ClientRpc(n),按其线路编码编号。你自己的客户端中继 RPC 出现在 ClientRpc 区间,服务器 RPC 出现在 ServerRpc 区间。
如果 EcsSnapshot 占出站流量的比例很大,说明玩家频繁跨越范围边界。快照是可靠发送且内容完整的,所以比随后的增量昂贵得多。