Not Enough Bandwidth (NEB)

简介
NEB 通过多种方法在 Minecraft 游戏过程中尽可能地节省网络流量,同时对模组和玩家保持透明。
在来自 [TeaCon Jiachen](teacon.cn) 的 ZZZZ 数据集中,与未经压缩的原始数据相比,NEB 理论上可将服务器出站流量降低至原始大小的 7.6%,实际测得约为 13.8%。
在原版环境下的测试中,服务器出站流量降低至原始大小的 18%。理论上,随着安装模组数量的增加,通过网络传输的内容会变得更大、更复杂,从而带来更好的压缩效果。
游戏中按 Alt+N 即可方便地查看网络流量状态。
主要功能
紧凑数据包头
优化 CustomPacketPayload 的编解码,将数据包头 Identifier(数据包类型)替换为紧凑的索引。这使得模组网络数据包头开销固定为 3-4 字节,而不再是数据包类型对应字符串的长度。
索引结构如下:
> ### 固定 8 位头部
> ```
> ┌------------- 1 byte (8 bits) ---------------┐
> │ function flags │
> ├---┬---┬-------------------------------------┤
> │ i │ t │ reserved (6 bits) │
> └---┴---┴-------------------------------------┘
> ```
> - i = indexed(1 位)
> - t = tight_indexed(1 位,仅在 i=1 时有效)
> - reserved = 6 位(保留以备将来使用)
>
> ### 已索引的数据包类型
> - 若 i=0(未索引):
> ```
> ┌---------------- N bytes ----------------
> │ Identifier (packet type) in UTF-8
> └-----------------------------------------
> ```
> - 若 i=1 且 t=0(已索引,非紧凑):
> ```
> ┌-------- 1 byte ---------┬-------- 1 byte --------┬-------- 1 byte --------┐
> ┌------------- 12 bits ---------------┬-------------- 12 bits --------------┐
> │ namespace-id (capacity 4096) │ path-id (capacity 4096) │
> └-------------------------------------┴-------------------------------------┘
> ```
> - 若 i=1 且 t=1(已索引,紧凑):
> ```
> ┌--------- 1 byte ----------┬--------- 1 byte ---------┐
> ┌--------- 8 bits ----------┬--------- 8 bits ---------┐
> │namespace-id (capacity 256)│ path-id (capacity 256) │
> └---------------------------┴--------------------------┘
> ```
> 然后是数据包内容。
当网络数据包命名空间及其对应路径少于 256 个时,占用 3 字节;当大于 256 时占用 4 字节。最多可支持 4096 个模组,每个模组 4096 个通道。
聚合与压缩
优化原版常常产生大量小数据包的情况。在 Connection 层级拦截传输,每 20ms 将其组装为一个大数据包,压缩后发送。
> ```
> ┌---┬----┬----┬----┬----┬----┬----...
> │ S │ p0 │ s0 │ d0 │ p1 │ s1 │ d1 ...
> └---┴----┴----┴----┴----┴----┴----...
> └--packet 1---┘└--packet 2---┘
> └----------compressed----------┘
> ```
> - S = varint,压缩后缓冲区的大小
> - p = prefix(medium/int/utf-8),该子数据包的类型
> - s = varint,该子数据包的大小
> - d = bytes,该子数据包的数据
延迟区块缓存
在原版中,当玩家移动时,服务器会指示客户端立即遗忘其身后的区块;如果玩家返回原位,则必须重新发送完整的区块数据。通过延迟这种"遗忘",可以节省来回探查时产生的区块传输流量。
配置
修改配置文件 config/NotEnoughBandwidthConfig.json。
compatibleMode
> 在客户端和服务端独立工作。
是否启用兼容模式。如果设置为 true,将使用下面的 blackList。
blackList
> 在客户端和服务端独立工作。
兼容模式的黑名单。NEB 将跳过此处列出的数据包。默认包含与 Velocity 相关的数据包列表,但您可以根据需要添加新的数据包。
> 为保证数据包顺序,黑名单中的数据包将会中断正在进行的聚合。如果黑名单中的数据包较多,或相应数据包发送过于频繁,将会降低聚合-压缩的效率。
contextLevel
> 在客户端和服务端独立工作。
压缩使用的上下文窗口大小。有效值为 21 到 25 的整数,分别代表 2MB 到 32MB。默认值为 23(8MB)。
更大的上下文窗口能带来更好的压缩效果和带宽节省,但会消耗更多内存。
> 对于一台拥有 100 名玩家的服务器,设置为 25 将额外消耗约 3200MB 内存。
dccSizeLimit, dccDistance, dccTimeout
> 仅在服务端工作。
延迟区块缓存(DCC)所允许的最大缓存区块数、缓存区块距离以及缓存超时时间。较大的值可能消耗更多内存,而较小的值可能更频繁地触发更新。