UDP 转发压力测试¶
本文记录 DraARL 单机 UDP fan-out 的优化前基线、全平台通用优化后的 Windows/Linux 单机结果,以及 2026-07-22 中心加三边缘的 Hyper-V 完整部署结果。测试用于定位代码瓶颈和辅助容量决策,不是生产 SLA;真实网卡、FRP、IPv6 和长时间稳态仍需在目标环境复测。
中心加三边缘的结果属于
edge分支历史兼容场景。当前dev的中心到中心互联只使用 HTTP/HTTPS 准入和主 UDP 端口,不能直接用本页的多边缘拓扑结果推断中心互联容量。
结论¶
- 优化前的稳定平台约为 5 万 pps;优化后在相同 Windows 回环环境达到 200,678 pps、零丢包,稳定吞吐至少提高 4 倍。
- Ubuntu 22.04 的 4 vCPU/8 GiB VM 内同时运行 MySQL、Redis、DraARL 和纯 Go 压测端,9000 台、20ms 连续 30 秒达到 449,950 pps、1,475.84 Mbps 应用层流量、零丢包,平均延迟 9.45ms。
- Linux 9000 台、19ms 时首次淘汰 1 个完整 fan-out 帧(0.1898%);15ms 时实际转发 573,236 pps、丢 4.50%,10ms 时维持约 554,338 pps、丢 38.4%。同机完整部署的保守零丢包上限是至少 45 万 pps,过载吞吐平台约 50 至 57 万 pps。
- Linux 20000 个真实 UDP socket、120ms 时达到 167,992 pps、零丢包;这是纯 Go bench 当前允许的最大设备档,不是服务端设备容量上限。
- Ubuntu 8 vCPU/8 GiB 中心加三个边缘、20000 个设备纯跨边缘转发时,30ms 达到约 667k pps、2.19 Gb/s DraARLv1 应用层流量且零丢包;20ms 时平台化在约 689k pps并出现 31.1% 丢包。
- 同一多边缘场景从 4 vCPU 提升到 8 vCPU 后,168k pps 的平均延迟由 31.6ms 降到 19.2ms;四个 DraARL 进程在 20000 设备时峰值合计约 346 MiB,说明该阶段 CPU 明显比内存敏感,8C8G 比 4C16G 更合适。
- 9000 个接收端、45ms 间隔时达到 200,678 pps、658.22 Mbps DraARLv1 应用层流量,平均延迟 13.5ms。
- 9000 个接收端、40ms 间隔时实际转发 220,476 pps,丢弃 2.0%,平均延迟升至 86.6ms,已经进入过载区。
- 15000 个在线设备、120ms 间隔时达到 125,992 pps、零丢包;18000 台在建立连接时由 Windows 压测进程先耗尽 socket/buffer 资源,未测到服务端上限。
- 5 个独立群组、每组 1000 台设备、5 个设备同时发送 Type 5 普通语音时为 41,625 pps、零丢包,并实际生成和清理 5 份录音。
- 1/2/4/8 writer 在 5000 台、120ms 下均零丢包,但平均延迟依次为 35.9/17.7/10.6/8.2ms,因此当前 Windows 配置选择 8 writer。
- Linux 4 vCPU 上的 1/2/4/8 writer 平均延迟依次为 11.08/5.39/5.18/5.74ms,因此 Linux 测试选择 4 writer;writer 数应按 CPU 和平台实测选择。
- Linux 45 万 pps 的稳定档已超过常见公网出口和 1GbE 可承载范围;当前不再计划
sendmmsg/recvmmsg/SO_REUSEPORT等 Linux 专属发送优化。 - 对当前业余无线电使用规模,单机容量已不是近期实现集群的充分理由。异地接入、高可用和超大路由域拆分仍是集群的独立价值。
测试环境¶
Windows¶
| 项目 | 配置 |
|---|---|
| 操作系统 | Windows,本机 IPv4 UDP 回环 |
| CPU | AMD Ryzen 9 7940HX,16 核 32 线程 |
| 内存 | 64 GB |
| Go | 1.25.5 windows/amd64 |
| UDP 服务 | DraARL 单机进程,监听 0.0.0.0:60050 (udp4) |
| MySQL | 本机 MySQL 8.0.12 |
| 完整报文 | 410 字节:90 字节 DraARLv1 头部 + 320 字节 DATA |
| 心跳 | 每台模拟设备约 2 秒一次 |
| writer | 8 个独立 Go FD 视图,保持相同监听源端口 |
| ingress | 单 reader,16 个按 username+SSID 稳定分片的 worker |
| 帧队列 | 64 个完整帧,最大帧龄 120ms |
| socket buffer | 接收、发送均请求并实际取得 4 MiB |
每个模拟设备绑定独立 127.x.x.x 地址,通过真实 DraARLv1 心跳认证上线。这样限速器仍参与测试,但不会由同 IP 限速掩盖转发表能力。结果中的 Mbps 只计算 DraARLv1 报文,不包含 UDP、IP、以太网、前导码和帧间隙。
Linux 4C8G 完整部署¶
| 项目 | 配置 |
|---|---|
| 虚拟化 | Microsoft Hyper-V,固定 4 vCPU、8 GiB(非动态内存) |
| 操作系统 | Ubuntu 22.04.5 LTS,Linux 6.8.0-134-generic,IPv4 UDP 回环 |
| CPU | AMD Ryzen 9 7940HX,VM 暴露 2 核 4 线程 |
| Go | 使用 Go 1.25.5 交叉编译的 linux/amd64 纯 Go 二进制 |
| 同机依赖 | MySQL 8.0.46、Redis 6.0.16、DraARL 服务、udp_fanout 压测端均在 VM 内运行 |
| UDP 配置 | 4 个独立 writer FD、4 个 ingress worker、64 帧队列、最大帧龄 120ms |
| 进程限制 | 服务和压测端均为 ulimit -n 200000 |
| 内核缓冲上限 | net.core.rmem_max=4194304、net.core.wmem_max=4194304;netdev_max_backlog 保持默认 1000 |
| socket buffer | 应用请求收发各 4 MiB;Linux 因内核记账加倍,启动日志读取到收发各 8 MiB |
| 完整报文 | 410 字节:90 字节 DraARLv1 头部 + 320 字节 DATA |
Linux 测试不是只跑孤立 UDP 服务:数据库、缓存、HTTP 管理服务和压测端共同竞争 4 vCPU/8 GiB,测试数据也由 bench 通过 VM 内 MySQL 创建和删除。所有终端仍使用独立 127.x.x.x 地址、真实心跳认证和普通 Go UDP socket;未使用 raw socket、Npcap 或 Linux 专属批量 I/O。因此它代表“单台 4C8G 完整部署”的同机回环能力,不等同于服务进程独占 CPU 或真实网卡容量。
优化内容¶
本轮不是简单增加 goroutine,而是调整整个热路径:
- fan-out 从每目标一个 job 改为每完整帧一个 job,接收者快照使用
netip.AddrPort并预分片。 - 每个 writer 使用独立的 Go
poll.FD和写锁;Windows 使用链式 socket 复制建立全部 8 个 writer,同时保持服务器监听源端口。 - 同一目标固定落到同一 writer,保持帧顺序;队列过载时淘汰最旧完整帧,不随机截断接收者。
- 入站改为单 reader 直接移交缓冲,并按 username+SSID 分片,避免同设备换源端口后乱序。
- 路由快速解码不再为语音物化 password/callsign 等无用字符串;转发前仍清空 password 字段。
- receiver snapshot 从每帧地址处理改为成员变化失效、30 秒兜底,并在构建时完成去重和 writer 分片。
- UDP 到 WebSocket 广播只复制一份只读 payload,多个连接共享引用;慢连接队列满时只计数。
- 删除设备运行时缓存的 10000 条硬上限,并批量加载 owner 信息。
Writer A/B¶
固定 5000 个在线设备、1 个发言者、120ms 间隔、Type 5、10 秒测量。理论输出约 41,992 pps。
| Writer | 实际下行 | 丢包率 | 平均延迟 | p95 上界 | 最大延迟 | 服务端 CPU |
|---|---|---|---|---|---|---|
| 1 | 41,992 pps | 0% | 35.9ms | 100ms | 85.3ms | 0.84 核 |
| 2 | 41,992 pps | 0% | 17.7ms | 50ms | 48.6ms | 0.75 核 |
| 4 | 41,992 pps | 0% | 10.6ms | 50ms | 29.1ms | 0.73 核 |
| 8 | 41,992 pps | 0% | 8.2ms | 20ms | 24.5ms | 0.90 核 |
这个负载不足以让单 writer 丢包,但并行 FD 明显降低了一个完整 fan-out 的完成时间。8 writer 相比 1 writer 平均延迟降低约 77%,CPU 没有随 writer 数线性增长。
单组规模¶
以下均使用 8 writer 和 Type 5。120ms 分档逐步增加持久化设备和真实 UDP socket。
| 在线设备 | 间隔 | 实际下行 | 应用层带宽 | 丢包率 | 平均延迟 | 最大延迟 | 服务端 CPU |
|---|---|---|---|---|---|---|---|
| 3000 | 120ms | 25,192 pps | 82.63 Mbps | 0% | 4.3ms | 11.8ms | 0.45 核 |
| 5000 | 120ms | 41,992 pps | 137.73 Mbps | 0% | 8.3ms | 24.3ms | 0.96 核 |
| 6000 | 120ms | 50,392 pps | 165.28 Mbps | 0% | 8.8ms | 27.9ms | 1.08 核 |
| 8000 | 120ms | 67,192 pps | 220.39 Mbps | 0% | 12.2ms | 35.4ms | 1.54 核 |
| 9000 | 120ms | 75,592 pps | 247.94 Mbps | 0% | 13.6ms | 43.5ms | 1.69 核 |
| 10000 | 120ms | 83,992 pps | 275.49 Mbps | 0% | 16.4ms | 56.0ms | 2.26 核 |
| 12000 | 120ms | 100,792 pps | 330.60 Mbps | 0% | 20.1ms | 60.0ms | 2.72 核 |
| 15000 | 120ms | 125,992 pps | 413.25 Mbps | 0% | 25.9ms | 68.9ms | 3.50 核 |
| 9000 | 60ms | 150,283 pps | 492.93 Mbps | 0% | 15.7ms | 56.2ms | 2.96 核 |
| 9000 | 45ms | 200,678 pps | 658.22 Mbps | 0% | 13.5ms | 57.3ms | 4.38 核 |
| 9000 | 40ms | 220,476 pps | 723.16 Mbps | 2.0% | 86.6ms | 164.5ms | 4.02 核 |
40ms 场景理论应收 2,249,750 个下行报文,实际少 44,995 个,恰好等于 5 个完整的 8999 目标 fan-out 帧。这与“过载时丢最旧完整帧”的策略一致,没有出现每帧固定尾部设备被随机截断的旧行为。
18000 台测试在连接阶段失败,Windows 返回 socket buffer/queue 资源不足。15000 台档已完成全量测量且零丢包;18000 的失败只能说明单进程本地压测器的资源上限,不能当作 DraARL 服务端容量边界。
多个独立群组与录音¶
Type 5 普通语音、5 个独立群组、每组 1000 台、每组一个同时发言者、120ms 间隔、15 秒测量:
| 群组布局 | 同时发言 | 实际下行 | 应用层带宽 | 丢包率 | 平均延迟 | 服务端 CPU | 录音 |
|---|---|---|---|---|---|---|---|
| 5 x 1000 | 5 | 41,625 pps | 136.53 Mbps | 0% | 8.9ms | 0.96 核 | 5 份 |
工具等待录音管线 42 秒完成异步落盘,确认生成 5 份录音后删除文件、通信记录和全部测试数据。多个独立路由域没有暴露新的全局锁瓶颈。
Linux 4C8G 完整部署结果¶
Writer A/B¶
固定 5000 台、120ms、Type 5、10 秒测量。全部档位均为 41,992 pps、零丢包;CPU 为进程全部 OS 线程的总 CPU 时间,不是仅主线程。
| Writer | 平均延迟 | p95 上界 | 最大延迟 | 服务端 CPU | 压测端 CPU | 服务 RSS |
|---|---|---|---|---|---|---|
| 1 | 11.078ms | 50ms | 36.470ms | 0.35 核 | 0.40 核 | 129.4 MiB |
| 2 | 5.386ms | 10ms | 15.338ms | 0.31 核 | 0.33 核 | 131.4 MiB |
| 4 | 5.178ms | 10ms | 12.049ms | 0.31 核 | 0.32 核 | 128.9 MiB |
| 8 | 5.742ms | 10ms | 20.553ms | 0.33 核 | 0.34 核 | 133.6 MiB |
1 writer 已能维持该档吞吐,但 4 writer 将平均 fan-out 延迟降低约 53%,且略优于 2/8 writer。8 writer 在 4 vCPU 上开始出现轻微调度收益递减,因此后续 Linux 数据统一使用 4 writer;这只是当前逐目标标准后端的最佳点,不是所有 Linux 主机都应固定为 4。
单组设备规模¶
以下使用 4 writer、120ms、Type 5、10 秒测量。20000 是纯 Go bench 当前设置的客户端上限。
| 在线设备 | 实际下行 | 应用层带宽 | 丢包率 | 平均延迟 | 最大延迟 | 服务端 CPU | 服务 RSS | 压测端 CPU | 压测端 RSS |
|---|---|---|---|---|---|---|---|---|---|
| 1000 | 8,392 pps | 27.52 Mbps | 0% | 1.483ms | 3.119ms | 0.09 核 | 130.9 MiB | 0.11 核 | 23.7 MiB |
| 3000 | 25,192 pps | 82.63 Mbps | 0% | 3.518ms | 7.450ms | 0.22 核 | 131.6 MiB | 0.25 核 | 46.4 MiB |
| 5000 | 41,992 pps | 137.73 Mbps | 0% | 5.247ms | 14.175ms | 0.31 核 | 136.4 MiB | 0.33 核 | 67.9 MiB |
| 8000 | 67,192 pps | 220.39 Mbps | 0% | 8.106ms | 22.755ms | 0.42 核 | 155.5 MiB | 0.41 核 | 98.8 MiB |
| 10000 | 83,992 pps | 275.49 Mbps | 0% | 10.212ms | 28.860ms | 0.51 核 | 165.8 MiB | 0.48 核 | 133.7 MiB |
| 12000 | 100,792 pps | 330.60 Mbps | 0% | 12.131ms | 44.541ms | 0.59 核 | 168.9 MiB | 0.55 核 | 136.5 MiB |
| 15000 | 125,992 pps | 413.25 Mbps | 0% | 15.052ms | 36.112ms | 0.70 核 | 187.1 MiB | 0.63 核 | 179.4 MiB |
| 18000 | 151,192 pps | 495.91 Mbps | 0% | 17.828ms | 42.678ms | 0.80 核 | 203.6 MiB | 0.71 核 | 215.5 MiB |
| 20000 | 167,992 pps | 551.01 Mbps | 0% | 20.180ms | 48.800ms | 0.88 核 | 200.1 MiB | 0.78 核 | 252.8 MiB |
设备规模增长时延迟、CPU 和内存近似平滑增长,没有再次出现旧版 10000 条设备加载上限或 8192 目标队列截尾。20000 台仍远未耗尽 4 个 vCPU;这里只能说明 bench 已跑满允许的设备数,不能把 20000 写成产品硬上限。
单组高包速与过载边界¶
固定 9000 台、4 writer、Type 5。20ms 档额外连续测量 30 秒,其余为 10 秒。
| 间隔 | 实际下行 | 应用层带宽 | 丢包率 | 平均延迟 | 最大延迟 | 服务端 CPU | 压测端 CPU |
|---|---|---|---|---|---|---|---|
| 60ms | 150,283 pps | 492.93 Mbps | 0% | 9.513ms | 23.829ms | 0.74 核 | 0.66 核 |
| 45ms | 200,678 pps | 658.22 Mbps | 0% | 9.246ms | 32.351ms | 0.85 核 | 0.74 核 |
| 40ms | 224,975 pps | 737.92 Mbps | 0% | 8.908ms | 30.538ms | 0.91 核 | 0.77 核 |
| 30ms | 300,567 pps | 985.86 Mbps | 0% | 8.849ms | 26.522ms | 1.12 核 | 0.93 核 |
| 25ms | 359,960 pps | 1,180.67 Mbps | 0% | 8.740ms | 35.736ms | 1.28 核 | 1.05 核 |
| 20ms,30 秒 | 449,950 pps | 1,475.84 Mbps | 0% | 9.449ms | 41.465ms | 1.69 核 | 1.36 核 |
| 19ms | 473,347 pps | 1,552.58 Mbps | 0.1898% | 9.466ms | 31.092ms | 1.66 核 | 1.35 核 |
| 18ms | 498,545 pps | 1,635.23 Mbps | 0.3597% | 54.138ms | 150.084ms | 1.85 核 | 1.49 核 |
| 17ms | 512,943 pps | 1,682.45 Mbps | 3.2258% | 68.443ms | 158.050ms | 1.85 核 | 1.45 核 |
| 16ms | 543,540 pps | 1,782.81 Mbps | 3.3600% | 112.073ms | 152.780ms | 1.86 核 | 1.47 核 |
| 15ms | 573,236 pps | 1,880.22 Mbps | 4.4978% | 101.070ms | 147.910ms | 1.87 核 | 1.46 核 |
| 10ms | 554,338 pps | 1,818.23 Mbps | 38.4000% | 123.485ms | 159.703ms | 1.84 核 | 1.45 核 |
20ms 的 30 秒档共应收并实际收到 13,498,500 个下行报文,可作为本环境保守的零丢包边界。19/18/17/16/15/10ms 分别少 1/2/19/21/30/384 个完整的 8999 目标 fan-out 帧,继续验证过载策略不会随机截断单帧尾部设备。
18ms 起服务和压测端合计约占 3.3 个用户态 CPU 核,剩余 CPU 还要处理同机回环网络栈、MySQL、Redis 和系统任务;服务端 CPU 在约 1.85 核处平台化。因此 50 至 57 万 pps 是这套“服务与负载同 VM”布局的联合过载吞吐,不应解释为 DraARL 独占 4 核或两机测试的发送上限。
多组 Type 5 与录音¶
| 群组布局 | 同时发言 | 实际下行 | 应用层带宽 | 丢包率 | 平均延迟 | 服务端 CPU | 压测端 CPU | 录音 |
|---|---|---|---|---|---|---|---|---|
| 5 x 1000 | 5 | 41,625 pps | 136.53 Mbps | 0% | 5.670ms | 0.33 核 | 0.35 核 | 5 份 |
VM 的全新数据库默认 comm.enabled=false,所以第一次 Type 5 只验证了转发且没有录音;显式启用通信录制并重启服务后,第二次测试生成 5 份独立 .raw 文件。工具等待异步上传和数据库同步后删除 5 个文件及全部测试行,最终测试用户和录音残留均为 0。这是配置默认值导致的预期差异,不是 Linux 录音回归。
中心加三个边缘¶
该组测试在同一 Ubuntu 22.04 VM 中运行 MySQL、Redis、中心、三个边缘和纯 Go bench。每个边缘拥有独立 UDP 入口,Type 5 先由来源边缘本地处理,再以一份 Type 0 Upstream 到中心;中心只按目标边缘展开 Downstream,由目标边缘完成设备级 fan-out。
三种布局含义如下:
local:所有设备进入同一个边缘,只测边缘本地 fan-out。distributed:同组设备轮转进入三个边缘,同时包含本地和跨边缘目标。cross:发言者位于第一个边缘,全部接收者位于其他边缘,排除来源边缘本地接收者。
4 vCPU/16 GiB¶
| 布局 | 设备 | 群组 | 间隔 | 实际下行 | 应用层带宽 | 丢包率 | 平均延迟 |
|---|---|---|---|---|---|---|---|
| local | 5000 | 5 | 120ms | 约 41.8k pps | 约 137 Mb/s | 0% | - |
| distributed | 5000 | 5 | 120ms | 约 41.8k pps | 约 137 Mb/s | 0% | - |
| cross | 10000 | 5 | 120ms | 约 84k pps | 约 275 Mb/s | 0% | - |
| cross | 20000 | 5 | 120ms | 约 168k pps | 约 551 Mb/s | 0% | 31.6ms |
本地、混合和纯跨边缘在相同目标数下没有出现额外丢包。20000 设备时中心与三个边缘合计 RSS 峰值约 346 MiB,16 GiB 内存没有形成约束。
8 vCPU/8 GiB¶
固定 20000 个会话和 5 个独立群组,复用会话逐档提高发包频率。下表是短时分档结果:
| 间隔 | 理论/实际下行 | 应用层带宽 | 丢包率 | 平均延迟 |
|---|---|---|---|---|
| 120ms | 约 167k pps | 约 551 Mb/s | 0% | 19.2ms |
| 60ms | 约 335k pps | 约 1.10 Gb/s | 0% | - |
| 30ms | 约 667k pps | 约 2.19 Gb/s | 0% | - |
| 20ms | 约 689k pps | 约 2.26 Gb/s | 31.1% | 进入过载 |
8 vCPU 在 168k pps 档将平均延迟从 4 vCPU 的 31.6ms 降到 19.2ms。30ms 档仍零丢包,20ms 后不再随输入线性增长。过载时两个目标边缘各约使用 2.3 个 CPU 核,负载端约使用 2.4 核,而中心仅约 0.05 核;瓶颈是共享 VM 中目标边缘逐设备 fan-out、UDP 接收端和内核路径,Type 0 中心调度不是瓶颈。
这组数据也说明 8C8G 比 4C16G 更适合作为当前完整部署压测规格:增加 CPU 显著降低延迟并提高零丢包吞吐,减少内存没有观察到负面影响。实际跨地域部署仍会先受到公网带宽、运营商质量和终端规模限制,回环得到的 2Gb/s 以上结果不能直接作为公网承诺。
8 vCPU/8 GiB,30 分钟静态 soak¶
固定 20000 个会话、5 个独立群组、纯跨边缘布局和 120ms 间隔连续发送 30 分钟:
| 发送包 | 理论下行 | 实际下行 | 丢包率 | 实际下行速率 | 应用层带宽 | 平均延迟 | p95 上界 | 最大延迟 |
|---|---|---|---|---|---|---|---|---|
| 75,000 | 299,925,000 | 299,911,002 | 0.0047% | 166,617 pps | 546.50 Mb/s | 22.530ms | 50ms | 301.732ms |
四个 DraARL 进程在测量阶段合计使用 2.21 个 CPU 核,RSS 为 319.9 MiB、峰值 361.6 MiB;其中中心仅使用 0.05 核,两个目标边缘各使用 1.07 核。负载端使用 1.36 核和 344.2 MiB RSS。
全部 13,998 个未送达目标都能由边缘设备侧 fan-out 指标精确解释:edge-b
记录 10,000 个目标丢弃,对应 5 个 2,000 目标的完整组帧;edge-c 记录 3,998
个目标丢弃,对应 2 个 1,999 目标的完整组帧。中心 fan-out、ingress、录音队列,
中心/边缘互联 drop/error、资源保护计数和三个边缘 UDP socket drops 均为 0。
因此这是实时队列对 7 个完整目标边缘帧的主动淘汰,没有观察到随机截断或来源不明的
散包丢失。
短时 120ms 档的零丢包不能外推成无限时长承诺;30 分钟结果更适合说明长期运行时 调度抖动会偶发触发完整帧保护。测试结束后 20000 个会话均按超时清零,测试用户、 设备、群组和通信记录残留均为 0。本轮站点未启用通信录制,因此没有生成录音文件; 录音正确性由前面的 5 组专项测试覆盖。
与旧基线比较¶
优化前基线提交为 647d197,以下是同一 Windows 环境的可比数据;优化前没有保留 Linux 结果,因此不能用 Linux 45 万 pps 计算代码优化倍数:
| 对比项 | 优化前 | 优化后 |
|---|---|---|
| 稳定零丢包下行 | 约 50,000 pps | 至少 200,678 pps |
| 5000 台、120ms 平均延迟 | 35.8ms | 8.2ms |
| 6000 台、120ms | 47,139 pps,5.71% 丢包 | 50,392 pps,0% 丢包 |
| 9000 台大帧 | 180ms 时已丢 14.65% | 120ms 时 75,592 pps,0% 丢包 |
| 队列单位 | 每目标 job,8192 槽 | 每完整帧,64 槽,限龄 120ms |
| writer 内核路径 | 多 goroutine 共用单个 Go FD 写锁 | 8 个独立 Go FD 写锁 |
当前瓶颈¶
逐目标系统调用已不是当前业务瓶颈¶
标准后端仍对每个目标执行一次 WriteToUDPAddrPort,理论上可用 Linux sendmmsg 继续减少系统调用。但当前 30 秒零丢包基线已经达到 449,950 pps、1,475.84 Mbps 应用层流量,先于程序触顶的会是常见公网出口、1GbE 物理链路和实际终端规模。继续增加 Linux 专属后端的复杂度没有现实收益,因此本轮明确停止在跨平台 standard 后端;只有未来出现超过当前边界的真实业务负载时才重新立项。
实时帧服务时间¶
Windows 在约 20 万 pps 时队列延迟仍健康,约 22 万 pps 开始完整淘汰帧;Linux 4C8G 同机布局在 45 万 pps 连续 30 秒仍健康,47.4 万 pps 偶发淘汰一帧,50 万 pps 以上排队延迟明显增长。增大队列只会把丢包转换成陈旧语音,因此保留当前 120ms 帧龄和完整帧淘汰策略作为容量保护,不再通过扩大队列追求压测数字。
Windows 回环与压测器¶
服务端和负载进程共享同一台主机及 Windows 网络栈。18k socket 失败、40ms 档的 4 核服务端 CPU 和约 4 核负载端 CPU 都说明测试结果包含回环交换及接收器成本。需要两机真实网卡测试才能区分应用、内核、NIC 和接收端上限。
Linux 同机资源竞争¶
Linux 过载档里 DraARL 约占 1.85 核,压测端约占 1.45 核,此外还有回环内核路径和同机依赖。吞吐平台出现时并非 DraARL 单进程已经用满 4 核,而是完整 VM 接近联合资源边界。两机测试可能提高服务端结果,也可能先撞到 NIC 线速;在此之前不能把约 57 万 pps 当成生产发送能力。
尚未覆盖¶
- 两机真实网卡及 1/2.5/10GbE 线速
- IPv6、FRP/PROXY 聚合流、NAT
- 大量慢 WebSocket 客户端
- 持续切组、禁收、上下线等成员 churn
- 带持续切组、禁收发、漫游和节点重连的 30 分钟 soak,以及 24 小时 soak
- CPU/mutex/block profile
容量建议¶
在这台 Windows 主机上,100,000 pps、12000 台设备、120ms 是已经实测的零丢包档,并为 200,000 pps 的本机拐点保留约 50% 余量。它可以作为开发环境的保守参考,不应直接换算成互联网生产承诺。
在 Linux 4C8G VM 的完整同机布局中,20,000 台/120ms 和 449,950 pps/20ms 已分别通过零丢包测试。若只按当前回环结果为应用留约三分之一余量,可用 300,000 pps 作为后续真实网络容量验证的起点;这仍不是生产 SLA,也不是继续优化发送器的目标。
真实部署还要受网卡线速影响。410 字节应用报文之外仍有 UDP/IP、链路层和帧间隙开销;Linux 的 30ms 档已是 985.86 Mbps 应用层流量,25ms 以上结果只有回环或超过 1GbE 的链路才可能承载。生产容量应在目标 Linux 服务器和真实网卡上重复测试后确定。
对当前面向业余无线电的规模,建议先保持单机架构。只有业务出现异地接入、高可用要求,或单个路由域在真实网络上确实超过单机余量时,再实现一主多从 UDP 子节点;中心节点应只向每个目标子节点发送一份帧,由子节点完成本地 fan-out。
复现¶
当前 bench 固定使用 Type 5,以下命令用于复测当前正式语音路径。
单组 120ms 分档:
go run ./test/bench/udp_fanout -confirm-test-data -server-pid <PID> -levels 3000,5000,6000,8000,9000 -duration 10s -interval 120ms
单组高包速:
go run ./test/bench/udp_fanout -confirm-test-data -server-pid <PID> -levels 9000 -duration 10s -interval 45ms
Linux 4C8G 的 30 秒零丢包边界复测:
ulimit -n 200000
./udp_fanout -confirm-test-data -server-pid <PID> -levels 9000 -duration 30s -interval 20ms
5 个群组、每组 1000 台、Type 5 和录音:
go run ./test/bench/udp_fanout -confirm-test-data -server-pid <PID> -groups 5 -levels 5000 -duration 15s -interval 120ms
Type 5 只有在站点通信录制设置 comm.enabled=true 时才会实际落盘;关闭时仍可测完整普通语音转发,但录音数应为 0。具体参数、安全说明和异常中断后的清理方式见 test/bench/udp_fanout/README.md。