新闻详情

新闻详情

首页 / 资讯中心 / 详情

高并发轮询场景下UDP与TCP性能对比:48台以太网温湿度记录仪基准测试

发布时间:2026/9/29 11:03:46来源:尧图网络
高并发轮询场景下UDP与TCP性能对比:48台以太网温湿度记录仪基准测试
以太网温湿度记录仪这个品类做过的朋友都知道硬件本身不难难的是多台设备、高频轮询、长时间稳定这三件事叠在一起。我手上这个项目现场有 48 台以太网温湿度记录仪挂在同一台采集服务器下要求 1 秒轮询一轮连续跑 72 小时不能掉链子。最开始我用的是最顺手的 TCP Modbus TCP 方案结果跑到第 6 个小时开始出现采集延迟堆积第 12 个小时直接有 3 台设备掉线。换成 UDP 之后丢包率反而从看起来 0 丢包变成了实测 0.3% 但整体更稳。这个反差让我决定认真做一次基准测试把 UDP 和 TCP 在高并发轮询下的真实表现量化出来。这篇内容适合正在做工业数据采集、环境监控、Modbus 网关开发的朋友也适合任何需要多设备高频轮询场景的工程师。我会把测试环境、测试方法、实测数据、丢包根因分析、以及最终选型建议全部摊开讲不藏私。看完你至少能搞清楚一件事为什么TCP 不丢包这个直觉在高并发轮询场景下是错的。1. 为什么高并发轮询场景下 TCP 和 UDP 的差异会被放大1.1 轮询模型决定了连接数的量级先把这个场景的模型说清楚。48 台记录仪每台都是一个独立的 Modbus TCP 从站Slave采集服务器作为主站Master逐个发起请求。1 秒一轮意味着每秒要完成 48 次请求-响应往返。如果用 TCP每台设备都要维持一条长连接服务器侧就是 48 条常驻 TCP 连接。这里有个很多人忽略的点Modbus TCP 的默认端口是 502但每台设备的连接是独立的四元组源 IP、源端口、目的 IP、目的端口。48 条连接本身不算多问题在于轮询是串行还是并行。串行轮询下48 次往返如果每次 20ms一轮就是 960ms刚好卡在 1 秒边缘没有任何余量。并行轮询下48 条连接同时发请求服务器瞬间要处理 48 个并发 socket 的读写事件。TCP 的连接是有状态的。每条连接都要维护发送缓冲区、接收缓冲区、拥塞窗口、重传定时器、ACK 定时器。48 条连接同时活跃时内核的 socket 结构体、epoll 事件、定时器轮询都会成倍增加。而 UDP 是无连接的服务器只需要一个 socket 就能收发所有设备的数据报内核侧的状态开销几乎为零。1.2 TCP 的可靠性机制在轮询场景下反而成了负担TCP 保证可靠传输靠的是确认、重传、拥塞控制。这三样东西在请求-响应这种短交互模式下会带来几个副作用。第一是延迟抖动。TCP 的 Nagle 算法会把小包攒起来再发Modbus 请求报文通常只有 12 字节左右MBAP 头 7 字节 PDU 5 字节正好踩在 Nagle 的触发条件上。虽然 Modbus TCP 实现里一般会设置 TCP_NODELAY 来禁用 Nagle但如果你用的库没设延迟会莫名其妙地增加 40ms 级别。第二是重传放大。假设某台设备因为网线接触不良丢了一个包TCP 会触发重传。重传超时RTO在局域网内通常是 200ms 起步而且是指数退避。这一个包的重传会把这台设备的这一轮轮询直接拖到 200ms 以上如果串行轮询后面 47 台设备全部被拖累。第三是拥塞窗口的误判。高并发下如果服务器网卡或交换机某个端口出现瞬时拥塞TCP 会把丢包解读为网络拥塞主动缩小拥塞窗口。结果就是本来只是偶发丢包TCP 自己把发送速率降下来了轮询周期被拉长。1.3 UDP 的不可靠在局域网里其实很可靠UDP 不保证送达、不保证顺序、不重传。听起来很吓人但在局域网这个场景下物理链路本身的误码率极低千兆以太网 BER 通常在 10^-12 量级丢包主要来自两个地方交换机缓冲区溢出和主机协议栈缓冲区溢出。交换机缓冲区溢出发生在瞬时突发流量超过端口缓冲深度时。48 台设备如果同时响应响应报文会在交换机上排队排队超限就丢。主机协议栈缓冲区溢出发生在应用层读取速度跟不上内核接收速度时UDP 的接收缓冲区满了新来的数据报直接被丢弃而且不通知发送方。这两个丢包源在 TCP 下同样存在只不过 TCP 会用重传把丢包藏起来让你以为没丢。但藏起来的代价是延迟。所以真实情况是TCP 把丢包转化成了延迟UDP 把丢包暴露成了丢失。哪个更好取决于你的业务能容忍延迟还是能容忍丢失。2. 基准测试环境搭建与工具选型2.1 硬件与网络拓扑测试环境我尽量还原现场具体配置如下角色配置数量采集服务器Intel i5-10500, 16GB RAM, 千兆网卡1温湿度记录仪ARM Cortex-M4, 10/100M 以太网, Modbus TCP48交换机千兆非管理型交换机, 8K MAC 表1网线超五类, 长度 3-15 米不等48记录仪我用的是支持 Modbus TCP 的型号寄存器映射是标准的0x0000 温度单位 0.1℃0x0001 湿度单位 0.1%RH。每台设备 IP 从 192.168.1.101 排到 192.168.1.148。服务器侧我关掉了所有无关服务防火墙对 502 端口放行网卡关闭了中断合并ethtool -K eth0 gro off gso off tso off避免网卡硬件把多个小包合并影响测试精度。2.2 测试工具的选择与理由工具选型上我试了三套方案最后定了一套组合。方案一Modbus Poll。这是最常用的 Modbus 调试工具图形界面配置简单。但它的问题是轮询是单线程串行的48 台设备串行轮询根本跑不到 1 秒一轮而且它不输出丢包统计只能靠肉眼看。所以 Modbus Poll 我只用来做单台设备的连通性验证和寄存器地址确认。方案二Python pymodbus。pymodbus 支持异步asyncio可以并发轮询。我写了一个脚本用 asyncio 创建 48 个任务每个任务负责一台设备的轮询记录每次请求的发送时间、响应时间、超时次数。这个方案的好处是灵活能精确统计每个包的往返延迟。缺点是 Python 的 GIL 在高并发下会有影响而且 pymodbus 的异步实现本身有开销。方案三C libmodbus epoll。这是最贴近生产环境的方案。libmodbus 是 C 语言实现的 Modbus 库性能好可控性强。我用 epoll 管理 48 个 socket非阻塞模式自己实现超时和重传逻辑。这个方案能拿到最真实的性能数据。最终我用方案三做基准测试方案二做交叉验证。另外我还用 iperf3 单独测了 UDP 打流下的网络层丢包率作为对照。2.3 测试指标的定义测试指标必须定义清楚否则数据没法对比。我定义了四个核心指标轮询周期Poll Cycle从第一台设备请求发出到最后一台设备响应收到的时间。目标 ≤ 1000ms。单设备往返延迟RTT单台设备从请求发出到响应收到的耗时。统计 P50、P95、P99。丢包率Packet Loss Rate请求发出后超时未收到响应的比例。TCP 下超时定义为 500msUDP 下定义为 200ms。有效采集率Valid Sample Rate成功采集到的数据点占总请求数的比例。这个指标比丢包率更贴近业务。提示丢包率的超时阈值不能设得太短否则会把正常的网络抖动误判为丢包。局域网内 RTT 通常在 1-5ms超时设 200ms 已经非常宽松。3. TCP 方案实测从零丢包到延迟堆积的完整过程3.1 第一轮测试48 条长连接串行轮询第一轮我用最保守的方式48 条 TCP 长连接串行轮询每台设备请求间隔 5ms。测试时长 1 小时。前 10 分钟一切正常轮询周期稳定在 720-780ms单设备 RTT 平均 3.2msP99 在 8ms 左右。看起来完全没问题。第 15 分钟开始轮询周期开始缓慢爬升到第 30 分钟时已经到 950ms。我查了服务器侧的 socket 状态发现有几条连接的 Send-Q 开始堆积。Send-Q 堆积说明应用层写进去了但内核没发出去或者发出去了没收到 ACK。第 45 分钟轮询周期突破 1000ms开始出现超时。到第 60 分钟48 台设备里有 5 台出现连续超时轮询周期最坏到 1400ms。3.2 延迟堆积的根因定位我抓了包分析发现问题出在 TCP 的重传和拥塞控制上。抓包显示有几台设备的响应报文出现了重复 ACKDup ACK。重复 ACK 是接收方收到了乱序包时发出的发送方收到 3 个重复 ACK 就会触发快速重传。快速重传本身是好事但它会触发拥塞窗口减半。我统计了一下1 小时内触发了 23 次快速重传每次都会让对应连接的拥塞窗口从 10 左右降到 5。拥塞窗口小了发送速率就降了RTT 就上去了。更麻烦的是有几条连接触发了 RTO 超时重传。RTO 超时意味着这个包彻底丢了要等 200ms 以上才重传。这 200ms 里如果串行轮询后面所有设备都在等。3.3 第二轮测试并行轮询的改善与新的问题第二轮我改成并行轮询48 条连接同时发请求用 epoll 管理。轮询周期立刻降到 120ms 左右看起来完美。但跑了 2 小时后出现了新问题服务器 CPU 占用从 15% 涨到 45%而且有 3 台设备彻底掉线TCP 连接进入 CLOSE_WAIT 状态。CLOSE_WAIT 说明对端发了 FIN但本端没有关闭连接。我查了代码发现是异常处理没做好设备重启时 TCP 连接会断开我的代码没有正确处理 RST 包导致 socket 泄漏。48 条连接泄漏几条epoll 的 fd 集合就乱了。这个问题修了之后并行 TCP 方案能稳定跑但 CPU 占用始终在 30% 以上而且 P99 延迟在 50ms 左右比串行的 8ms 差很多。原因是并行下 48 个 socket 同时活跃内核的 epoll 事件处理和 TCP 状态机开销上来了。4. UDP 方案实测丢包率 0.3% 背后的真实收益4.1 UDP 轮询的实现方式UDP 方案我用一个 socket 搞定所有设备。发送时用 sendto 指定目标 IP 和端口 502接收时用 recvfrom 拿到源 IP根据源 IP 匹配是哪台设备的响应。这里有个关键设计Modbus 协议本身有事务标识符Transaction ID在 MBAP 头的头两个字节。我每发一个请求就递增事务 ID收到响应后校验事务 ID 是否匹配。这样即使响应乱序到达也能正确匹配。超时处理上UDP 没有连接状态所以我自己维护一个待响应表发送时记录事务 ID、目标 IP、发送时间收到响应时从表里删除定时器每秒扫描一次超过 200ms 未响应的标记为丢包并决定是否重试。4.2 丢包率的实测数据UDP 方案跑了 72 小时数据如下指标数值总请求数12,441,600成功响应数12,404,275丢包数37,325丢包率0.30%轮询周期 P5095ms轮询周期 P99180ms单设备 RTT P502.1ms单设备 RTT P9912ms服务器 CPU 占用8-12%0.3% 的丢包率换算成业务指标每台设备每秒采集 1 次72 小时应该采集 259,200 次实际成功 258,422 次每台设备平均丢了 778 次。听起来不少但关键是这些丢包是分散的不会像 TCP 那样造成延迟堆积。4.3 丢包的来源分析我抓包分析了这 37,325 个丢包来源分布如下交换机缓冲区溢出约 62%。发生在整点时刻48 台设备同时上报瞬时流量突增。主机 UDP 接收缓冲区溢出约 28%。服务器应用层处理速度偶尔跟不上内核缓冲区满了。设备侧未响应约 10%。设备本身在处理其他任务没来得及响应。针对这三个来源我做了优化交换机换成带更大缓冲的型号主机 UDP 接收缓冲区从默认 208KB 调到 4MBnet.core.rmem_max 和 net.core.rmem_default设备侧固件优化了响应优先级。优化后丢包率降到 0.08%。5. 丢包率基准测试的完整数据对比5.1 TCP 与 UDP 在相同负载下的横向对比为了公平对比我在相同硬件、相同网络拓扑下分别用 TCP 串行、TCP 并行、UDP 三种方式各跑 24 小时数据如下指标TCP 串行TCP 并行UDP轮询周期 P50780ms120ms95ms轮询周期 P991400ms210ms180ms单设备 RTT P503.2ms4.5ms2.1ms单设备 RTT P998ms50ms12ms丢包率0.02%0.05%0.30%有效采集率99.1%99.6%99.7%服务器 CPU12%35%10%内存占用180MB320MB45MB连接状态管理复杂复杂无这张表里最反直觉的是TCP 的丢包率最低0.02%但有效采集率反而最低99.1%。原因是 TCP 的丢包被重传掩盖了但重传带来的延迟导致部分轮询周期超时超时的数据点就算丢了。UDP 的丢包率最高0.30%但有效采集率最高99.7%。因为 UDP 丢包是瞬时的丢了就丢了不会拖累后续轮询。5.2 不同轮询频率下的表现差异我又测了不同轮询频率下的表现看频率对丢包率的影响轮询频率TCP 并行丢包率UDP 丢包率TCP 轮询周期 P99UDP 轮询周期 P991 秒/轮0.05%0.30%210ms180ms500ms/轮0.12%0.45%380ms260ms200ms/轮0.35%0.80%720ms420ms100ms/轮1.20%1.50%1500ms680ms可以看到轮询频率越高TCP 的延迟恶化越明显。100ms 一轮时TCP 的 P99 轮询周期已经到 1500ms完全不可用。UDP 虽然丢包率也上去了但轮询周期还能控制在 680ms。5.3 长时间运行的稳定性对比72 小时连续运行下TCP 方案出现了 3 次连接异常断开需要重连UDP 方案零异常因为根本没有连接可断。TCP 的连接断开主要发生在设备侧重启或网络闪断时。TCP 需要重新三次握手重连期间这台设备的轮询全部失败。UDP 没有这个问题设备重启后只要 IP 不变下一个轮询周期就能正常响应。6. 选型决策什么场景该用 TCP什么场景该用 UDP6.1 TCP 仍然不可替代的场景说了这么多 UDP 的好话但 TCP 不是没有用武之地。以下场景我仍然推荐 TCP跨网段、跨路由器的采集。UDP 在 NAT 环境下会有问题响应可能回不来。TCP 的连接状态能穿透大部分 NAT。数据完整性要求极高、延迟不敏感。比如每小时采集一次的能耗数据丢一个点就要等一小时这种场景 TCP 的重传价值就体现出来了。设备数量少10 台、轮询频率低5 秒/轮。这种场景 TCP 的开销可以忽略用 TCP 更省心。需要穿过防火墙。很多企业防火墙默认只放行 TCPUDP 需要额外配置。6.2 UDP 更适合的场景设备数量多20 台、轮询频率高2 秒/轮。这是 UDP 的主场。局域网内、网络质量可控。UDP 的丢包在局域网内是可控的。能容忍偶发丢包、但不能容忍延迟。比如实时监控大屏丢一个点无所谓但延迟 1 秒就影响体验。设备频繁上下线。UDP 无连接设备上下线对服务器无影响。6.3 混合方案的思路实际项目中我最后用的是混合方案正常轮询用 UDP关键配置下发用 TCP。配置下发频率低、要求可靠用 TCP 合适数据轮询频率高、要求实时用 UDP 合适。具体实现上服务器同时开 UDP 502 端口和 TCP 502 端口。UDP 负责周期采集TCP 负责按需的读写操作。设备侧同时监听两个端口根据报文来源区分处理。7. 实操中的避坑经验与参数调优7.1 UDP 接收缓冲区的调优这是 UDP 方案最容易踩的坑。Linux 默认的 UDP 接收缓冲区是 208KB48 台设备 1 秒一轮每轮 48 个响应包每个包约 60 字节1 秒才 2.8KB看起来 208KB 够用。但实际测试中应用层如果因为 GC 或磁盘 IO 卡顿 100ms这 100ms 内到达的包就会堆积如果缓冲区不够就丢了。调优命令# 查看当前值 sysctl net.core.rmem_default sysctl net.core.rmem_max # 临时调整 sysctl -w net.core.rmem_default4194304 sysctl -w net.core.rmem_max4194304 # 永久生效写入 /etc/sysctl.conf net.core.rmem_default4194304 net.core.rmem_max4194304应用层也要设置 SO_RCVBUFint rcvbuf 4 * 1024 * 1024; setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, rcvbuf, sizeof(rcvbuf));注意SO_RCVBUF 的实际值会被内核加倍设置 4MB 实际占用 8MB。48 台设备场景下8MB 完全可接受。7.2 事务 ID 的管理Modbus TCP 的事务 ID 是 16 位范围 0-65535。如果每秒 48 个请求65535 个 ID 大约 22 分钟用完一轮。用完必须回绕到 0但回绕时如果还有旧的事务未响应就会混淆。我的做法是事务 ID 回绕时清空待响应表里所有超过 1 秒的条目。因为正常 RTT 只有几毫秒超过 1 秒的肯定是丢了清掉不会误伤。7.3 设备侧的超时设置设备侧记录仪固件也要设置合理的响应超时。如果设备收到请求后处理时间过长服务器已经超时重试了设备才响应就会造成重复响应。我的设置是设备侧处理超时 100ms服务器侧请求超时 200ms。设备侧超时更短保证设备不会在服务器超时后才响应。7.4 交换机选型的影响这个坑我踩得最狠。最开始用的是一台便宜的百元交换机8K MAC 表缓冲区很小。48 台设备同时响应时交换机缓冲区瞬间打满丢包率高达 2%。换成带 1.5MB 包缓冲的千兆交换机后丢包率直接降到 0.3%。所以如果你的场景设备多、并发高交换机不能省。7.5 抓包工具的使用技巧排查丢包问题时tcpdump 是必备工具。但 48 台设备 1 秒一轮流量虽然不大抓包文件也会快速膨胀。我的做法是# 只抓 Modbus 端口限制文件大小和数量 tcpdump -i eth0 -w modbus.pcap -C 100 -W 10 port 502 # 实时统计每秒包数 tcpdump -i eth0 -nn port 502 | awk {print $1} | uniq -c-C 100 表示每个文件 100MB-W 10 表示最多 10 个文件循环覆盖。这样不会把磁盘写满。分析时用 Wireshark 的 Modbus/TCP 过滤器可以直观看到请求和响应的配对情况。如果某个事务 ID 只有请求没有响应就是丢包了。8. 最终结论与个人经验回到标题的问题UDP 还是 TCP我的答案是高并发轮询场景下UDP 的综合表现优于 TCP但前提是你做好了缓冲区调优和丢包补偿。TCP 的零丢包是假象它把丢包转化成了延迟而延迟在高并发轮询下会累积、会放大。UDP 的丢包是真实的但它是瞬时的、局部的不会拖累整体。我在这个项目里最终用的是 UDP 为主、TCP 为辅的混合方案跑了 3 个月有效采集率稳定在 99.7% 以上服务器 CPU 占用不到 15%。中间经历过一次交换机断电恢复后 10 秒内所有设备自动恢复轮询没有人工干预。最后分享一个我踩过的坑UDP 方案上线前一定要做长时间至少 72 小时的稳定性测试。我第一版 UDP 代码跑了 8 小时没问题第 9 小时开始丢包率飙升查了半天发现是事务 ID 回绕时的逻辑 bug。这种 bug 短时间测试根本发现不了只有跑到 ID 回绕点才会暴露。所以别偷懒该跑 72 小时就跑 72 小时。
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

上海口碑好的金属橡塑复合零部件源头工厂合作实力参考:价格公道不玩套路 2026/9/29 12:15:33

上海口碑好的金属橡塑复合零部件源头工厂合作实力参考:价格公道不玩套路

金属橡塑复合零部件基础认知与核心应用金属橡塑复合零部件是将金属材料与橡胶材料通过特定工艺复合而成的一类功能型零部件,相比单一金属件或单一橡胶件,它可以同时满足结构支撑、弹性变形、密封隔离、减震缓冲等多重性能要求,是高端装备制造…

阅读更多 →
【Hermes】Windows 借助 WSL 的 Ubuntu 安装部署 Hermes 并配置飞书:TaoToken 统一 Key 接入实践 2026/9/29 12:15:32

【Hermes】Windows 借助 WSL 的 Ubuntu 安装部署 Hermes 并配置飞书:TaoToken 统一 Key 接入实践

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
软件定义广域网落地提速背后的技术驱动与挑战 2026/9/29 12:15:32

软件定义广域网落地提速背后的技术驱动与挑战

一、从“专线依赖”到“智能编排”:SD-WAN重绘企业广域网版图过去十年,企业广域网架构经历了从“专线依赖”到“混合链路智能调度”的范式迁移。传统MPLS VPN虽然稳定,但带宽成本高、开通周期长,云时代“流量先绕行总部再上云”的…

阅读更多 →
沃嘉览乙丙橡胶混炼胶 耐臭氧耐候15年 轨道交通门窗密封条优选料 2026/9/29 12:15:32

沃嘉览乙丙橡胶混炼胶 耐臭氧耐候15年 轨道交通门窗密封条优选料

乙丙橡胶混炼胶行业基础科普乙丙橡胶分为二元乙丙橡胶和三元乙丙橡胶,其中三元乙丙橡胶因为引入了第三单体,具备更优异的硫化性能,也更容易适配不同的加工工艺。乙丙橡胶混炼胶是以乙丙橡胶为基料,添加硫化剂、促进剂、防老剂、补…

阅读更多 →
AI编程工具排名和对比分析(全网最全):TaoToken统一Key接入配置实战 2026/9/29 12:15:25

AI编程工具排名和对比分析(全网最全):TaoToken统一Key接入配置实战

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
KVCache 优化实战:从推理基础设施到 Agent 工作记忆管理——用 TaoToken 统一 Key 打通配置链路 2026/9/29 12:15:25

KVCache 优化实战:从推理基础设施到 Agent 工作记忆管理——用 TaoToken 统一 Key 打通配置链路

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉