性能比拼: TCP vs UDP(重大改进)

本内容是对知名性能评测博主 Anton Putra TCP vs UDP Performance: HUGE Improvement! 内容的翻译与整理, 有适当删减, 相关指标和结论以原作为准

在本期视频中,我们将再次对比 TCP 和 UDP 协议,重点关注延迟(latency)和吞吐量(throughput)。在我进行另一个基准测试时,我发现了几个可以改进之前测试的方法,因此我决定与大家分享这些内容。


TCP 协议是如何工作的?

首先,让我们了解一下 TCP 协议的工作方式。

客户端和服务器之间需要建立连接,这通过 三次握手 来完成。

  1. 首先,发送方发送一个 "同步"(SYN)数据包给接收方,表示客户端希望发起连接,并提供一个随机的序列号,这个序列号将在后续数据传输中使用。
  2. 然后,接收方回应一个 "同步-确认"(SYN-ACK)数据包,表示"收到!这是我的序列号,并且我确认你的序列号。"
  3. 最后,发送方回复一个 "确认"(ACK)数据包,序列号加 1,并确认:"很好,我们同步了,可以通信了。"

我们可以使用 Wireshark 工具进行观察。为了简化,我们可以监听本地回环地址(localhost),并设置抓包过滤器,只捕捉端口为 8080 的数据包(无论是源端口还是目标端口)。

此刻我们还没有任何数据包,所以我将先启动服务器,然后发送一个 JSON 负载。

现在我们可以看到 TCP 的三次握手过程了:包括 SYN、SYN-ACK 和最终的 ACK 数据包,表明一个 TCP 连接已经建立。

我运行的服务器监听的是 8080 端口,但当你创建客户端时,它会随机选择一个端口来创建 TCP 套接字,并连接到服务器。

你还可以看到服务器向客户端发送了一个 JSON 消息,而客户端在接收到该消息后,会返回一个仅包含头部的空数据包,表示它已经收到了消息。


测试

为了进行测试,我使用了 AWS 平台。在这次测试中,我为参与测试的每个应用程序分别使用了一台 m7a.medium 实例

我使用 C++ 和原始套接字(raw sockets) 实现了 TCP 和 UDP 消息的发送与接收。

相关的源代码已经发布在我的公共 GitHub 仓库中

我将从与上一次测试完全相同的设置开始,整个测试分为两个阶段:

  • 第一阶段 ,我们只发送 16,000 条消息。你会发现,UDP 的延迟更低---这在意料之中,因为 UDP 不需要建立连接,也不需要确认接收。
  • 第二阶段,我们尝试使用 TCP 和 UDP 各自发送尽可能多的数据。你会注意到,由于 TCP 拥有更好的拥塞控制机制,它能实现更高的吞吐量。

最终测试结果非常值得注意:

  • TCP 的吞吐量可达约 620,000 条消息/秒
  • UDP 的吞吐量则只有 310,000 条消息/秒

不过,在最大负载下,你也会发现延迟差异变得更明显。UDP 在需要低延迟的场景下表现更好,而 TCP 在你更关注吞吐量和可靠性时表现更优秀。


第一个改进

我原以为使用 CMake 构建项目时,默认会生成一个经过优化的、可用于生产环境的二进制文件。

但我错了。

所以在下一轮测试中,我将使用 release 模式重新编译相同的源代码。

测试仍然分为两个阶段:

  • 第一阶段基本与之前相同,可能会看到 稍微降低的 CPU 使用率,但没有显著变化。
  • 第二阶段中,TCP 的吞吐量提升到了 1,000,000 条消息/秒,令人惊讶的是,UDP 的吞吐量反而没有增加,不过延迟有所降低。

因此,即使是简单地将应用程序编译为 release 模式,也能同时提升两个协议的表现。

这是一个愚蠢的错误,我没有任何借口。不过它确实展示了:通过正确编译应用程序可以获得更高的性能。


第二个改进

最后一个改进其实涉及到 监控(monitoring)

我知道给应用程序添加指标会降低性能,但我以前从未实际测量过影响到底有多大。

所以,我使用 Prometheus 的直方图(histogram) 来测量客户端发送和接收的 UDP 与 TCP 消息的延迟。

很多人在生产环境中也会这么做,但如果你测量的是类似原始 TCP 或 UDP 数据包这种层级的内容,那么这些测量行为本身就会影响性能。

因此,在下一次测试中,我继续使用 Prometheus 的计数器(counter) 来计算接收到的消息速率,但我关闭了 histogram。这样你在最终测试中将看不到延迟的统计。这是第一阶段。

在第二阶段,我们可以看到:

  • TCP 达到了 1,100,000 次请求/秒 ,比上一个测试提升了 10%
  • UDP 也有相同程度的提升,现在约为 420,000 条消息/秒

这个测试说明,仅仅是为高性能应用程序添加监控指标,就可能导致性能下降 10% 或更多 。所以一定要非常小心 --- 每一次函数调用和性能测量,都会降低程序的运行效率。

这在例如 交易系统 这样的场景中尤其重要,因为每一微秒都至关重要。


在下一期视频中,我将对比 WebSockets 与 HTTP 或 REST API 的表现。但在此之前,你可以先查看我关于 数据库、缓存以及不同编程语言 的其他基准测试。


相关推荐
2503_924806853 小时前
动态IP使用中 报错407 怎么办???
服务器·tcp/ip·php
小白银子3 小时前
零基础从头教学Linux(Day 42)
linux·运维·服务器·网络·nginx
火星MARK4 小时前
如何配置 Ingress 的 SSL/TLS 证书?
网络·网络协议·ssl
看好多桂花树4 小时前
Nginx SSL/TLS 配置
网络·nginx·ssl
程序猿费益洲5 小时前
Docker 网络详解:(一)Linux 网络虚拟化技术
linux·网络·docker·容器·云计算
shylyly_5 小时前
Linux-> UDP 编程3
linux·运维·网络协议·udp·bind·cs·聊天室程序
云宏信息6 小时前
赛迪顾问《2025中国虚拟化市场研究报告》解读丨虚拟化市场迈向“多元算力架构”,国产化与AI驱动成关键变量
网络·人工智能·ai·容器·性能优化·架构·云计算
歪歪1006 小时前
什么是TCP/UDP/HTTP?
开发语言·网络·网络协议·tcp/ip·http·udp
luckys.one6 小时前
第12篇|[特殊字符] Freqtrade 交易所接入全解:API、WebSocket、限频配置详解
网络·ide·python·websocket·网络协议·flask·流量运营
roman_日积跬步-终至千里7 小时前
【系统架构设计(36)】网络规划与设计
网络·系统架构