选传输协议不是选”最好的”——是选”最适合你的场景的”。
TCP 是默认选择,但不是最优选择。UDP 快但需要自己造轮子。QUIC 是未来但生态未成熟。SCTP 技术完美但部署不了。每种协议都有其设计取舍,理解这些取舍才能做出有依据的选型决策。
本文不再重复每个协议的协议细节(前面的文章已经讲透了),而是聚焦于选型方法论——面对一个具体场景,怎么在这四种协议之间做出决策?决策的维度是什么?每个选择的代价是什么?
一、四种协议的核心定位
在深入对比之前,先明确每种协议的设计哲学和核心价值主张:
TCP (RFC 793, 1981)
设计哲学: 可靠、有序、面向连接的字节流
核心价值: 通用性 — 几乎所有场景都能用,生态最完善
设计取舍: 用延迟换可靠性(重传阻塞),用复杂性换通用性
UDP (RFC 768, 1980)
设计哲学: 最小化传输层 — 只提供端口复用和校验和
核心价值: 自由度 — 应用层可以精确控制传输行为
设计取舍: 不提供任何保障(可靠性、有序、流控全部需要自建)
QUIC (RFC 9000, 2021)
设计哲学: 在 UDP 上重建传输层,同时内置加密
核心价值: 低延迟 + 安全 — 1-RTT 握手含 TLS,连接迁移
设计取舍: 用 CPU 开销换功能(用户态协议栈 + 强制加密)
SCTP (RFC 9260, 2022, 原 RFC 4960)
设计哲学: 修复 TCP 的结构性缺陷(单流、单路径)
核心价值: 多流 + 多宿主 — 消除队头阻塞,自动故障切换
设计取舍: 技术优越但部署受限(NAT/防火墙不支持)
一句话总结:TCP 是安全牌,UDP 是自由度,QUIC 是未来赌注,SCTP 是受限场景的最优解。
二、四维对比框架
传输协议的选型可以归结为四个核心维度:延迟(Latency)、吞吐量(Throughput)、可靠性(Reliability)和部署可行性(Deployability)。
2.1 延迟对比
TCP UDP QUIC SCTP
连接建立:
无加密 1.5 RTT 0 1 RTT 2 RTT
TLS 1.2 3.5 RTT N/A N/A 4 RTT
TLS 1.3 2.5 RTT N/A 1 RTT 3 RTT
恢复连接 1 RTT 0 0 RTT 2 RTT
数据传输延迟:
正常传输 基线 最低 略高于TCP 类似TCP
丢包时 高(HoL) 无影响 低(流隔离) 低(流隔离)
拥塞时 高(cwnd) 无感知 中(BBR) 高(cwnd)
尾延迟 (P99):
无丢包 低 最低 中 低
1% 丢包 高 低 中 中
5% 丢包 很高 中 高 高
延迟分析的几个关键观察:
连接建立延迟。 QUIC 的 1-RTT(含 TLS)握手是其最大的延迟优势。TCP + TLS 1.3 需要 2.5 RTT(TCP 握手 1 RTT + TLS 1 RTT + 半个 RTT 的数据发送确认),QUIC 将传输层和加密层握手合并为 1 RTT。对于短连接场景(如移动端 API 调用),这个差异直接影响用户体验。
队头阻塞延迟。 TCP 的单流模型导致任何丢包都会阻塞所有后续数据的交付。在多路复用场景(HTTP/2)中,这意味着一个 Stream 的丢包会阻塞所有 Stream。QUIC 和 SCTP 的多流模型将这个影响限制在单个 Stream 内。
尾延迟。 UDP 在高丢包环境下的尾延迟最低,因为应用层可以选择不重传过时的数据。TCP 和 SCTP 的可靠传输保证意味着丢包必须重传,这在高丢包环境下会导致 P99 延迟急剧上升。
# 测量各协议的连接建立延迟
# TCP + TLS 1.3:
curl -w "TCP: %{time_connect}s, TLS: %{time_appconnect}s, \
TTFB: %{time_starttransfer}s\n" -o /dev/null -s https://example.com
# 典型结果(RTT=50ms 的跨地域连接):
# TCP: 0.050s (1 RTT)
# TLS: 0.150s (TCP + TLS = 3 RTT)
# TTFB: 0.200s (+ 服务端处理)
# QUIC (用 curl 的 HTTP/3 支持):
curl --http3 -w "QUIC: %{time_appconnect}s, \
TTFB: %{time_starttransfer}s\n" -o /dev/null -s https://example.com
# 典型结果:
# QUIC: 0.050s (1 RTT, 含 TLS)
# TTFB: 0.100s (比 TCP+TLS 快 ~50ms)
# UDP 延迟(以 DNS 查询为例):
dig @8.8.8.8 example.com | grep "Query time"
# Query time: 20 msec
# 无握手开销,直接发送查询2.2 吞吐量对比
TCP UDP QUIC SCTP
最大吞吐:
内核态 高 最高 N/A 高
用户态 高 最高 中高 中
硬件卸载 支持 支持 有限 有限
拥塞控制:
内置 是(必须) 无 是(必须) 是(必须)
算法选择 多种 N/A 多种 有限
公平性 好 无保证 好 好
吞吐量影响因素:
协议头开销 20B 8B 变长~20B 16B+
加密开销 可选 可选 强制 可选
用户态/内核态 内核 内核 用户态 内核
# 吞吐量基准测试
# TCP 吞吐量 (iperf3):
iperf3 -c target -t 30 -P 4
# -P 4: 4 个并行流
# 典型 10G 网络结果: ~9.4 Gbps
# UDP 吞吐量:
iperf3 -c target -u -b 10G -t 30
# -u: UDP 模式
# -b 10G: 目标带宽
# 典型结果: ~9.8 Gbps (更少的协议开销)
# 注意 UDP 无拥塞控制,高带宽发送可能导致网络拥塞
# QUIC 吞吐量受限因素:
# 1. 用户态协议栈: 数据需要在用户态和内核态之间拷贝
# 2. 强制加密: AES-GCM/ChaCha20 加密开销
# 3. ACK 处理: 用户态处理 ACK 比内核态慢
# 4. GSO/GRO 支持: 正在改进但不如 TCP 成熟
# 实测: 高性能 QUIC 库 (quiche, msquic) 可达 TCP 吞吐量的 70-90%2.3 可靠性对比
TCP UDP QUIC SCTP
数据可靠性:
保证交付 是 否 是 是/部分
有序交付 是(全局) 否 是(流内) 是(流内)
消息边界 否(字节流) 是 是(流) 是(消息)
部分可靠 否 N/A 实验性 是(PR-SCTP)
连接可靠性:
故障检测 Keepalive 无 内置探测 Heartbeat
故障切换 无 N/A 连接迁移 多宿主
连接迁移 否 N/A 是(CID) 否(但多IP)
错误处理:
校验和 16-bit 16-bit N/A(TLS) CRC-32c
校验范围 头+数据 头+数据 TLS保护 头+数据
可靠性选型的关键问题:
你的数据能容忍丢失吗? 如果不能(金融交易、文件传输、数据库复制),TCP/QUIC/SCTP 是唯一的选择。如果能(实时视频、游戏状态、传感器遥测),UDP 或 PR-SCTP 允许你用可靠性换延迟。
你需要全局有序还是部分有序? TCP 的全局有序在多路复用场景下导致队头阻塞。如果你的消息在逻辑上是独立的(如不同 RPC 请求),QUIC 和 SCTP 的流内有序 + 流间无序是更好的选择。
你需要消息边界吗? TCP 是字节流——应用层必须自己实现消息分帧(长度前缀、分隔符、HTTP Chunk)。SCTP 和 UDP 原生保留消息边界。QUIC 的 Stream 虽然也是字节流,但 DATAGRAM 帧(RFC 9221)提供了消息语义。
2.4 部署可行性对比
TCP UDP QUIC SCTP
网络兼容:
NAT 穿越 好 好 好(UDP) 差
防火墙友好 好 中 中(UDP) 差
中间设备透明 差* 好 好** 差
平台支持:
操作系统内核 所有 所有 部分 Linux/BSD
浏览器 是 否 是(HTTP/3) 否***
移动平台 是 是 是 否
嵌入式/IoT 是 是 部分 部分
生态成熟度:
库/框架 最丰富 丰富 快速增长 有限
运维工具 最成熟 成熟 发展中 电信专用
开发者认知 最高 高 增长中 低
调试工具 最完善 完善 发展中 有限
* TCP 受中间设备干扰: 某些 middlebox 会修改 TCP 选项、重写窗口大小
** QUIC 加密头部,中间设备无法干扰但也无法优化
*** WebRTC DataChannel 用 SCTP over DTLS over UDP,但这不是原生 SCTP
部署可行性是一个经常被低估的选型因素。技术上的最优解如果无法部署,就不是工程上的最优解。
# 检测目标路径对各协议的支持
# TCP: 几乎 100% 可达
nc -zv target 443
# UDP: 大部分路径可达,但某些企业网络阻止
nc -zuv target 443
# QUIC (UDP 443): 取决于路径上的防火墙策略
# 约 3-5% 的网络路径阻止 UDP 443
curl --http3 -v https://target 2>&1 | grep -i "quic\|h3"
# SCTP: 大部分公网路径不可达
nmap -sY -p 3868 target
# filtered → 路径上的 NAT/防火墙丢弃了 SCTP三、场景选型决策
3.1 Web 服务(HTTP API / 网站)
场景特征:
- 请求-响应模型,短连接或连接池
- 需要 TLS 加密
- 全球用户,经过各种网络设备
- 需要 CDN 和负载均衡支持
推荐选型:
首选: TCP + TLS 1.3 (HTTP/2)
✓ 生态最成熟(Nginx/HAProxy/Envoy 全支持)
✓ CDN 全面支持
✓ 100% 网络路径可达
✓ 成熟的连接池和 Keep-Alive 机制
进阶: QUIC (HTTP/3)
✓ 连接建立更快(1-RTT vs 2.5-RTT)
✓ 多路复用无队头阻塞
✓ 移动端网络切换不断连
✗ CDN/LB 支持仍在完善
✗ ~5% 路径不可达,需要回退到 TCP
不推荐: UDP / SCTP
✗ 需要自建可靠传输
✗ 没有浏览器支持
Web 服务的典型迁移路径:
阶段 1: TCP + TLS 1.3 + HTTP/2
→ 大部分服务的当前最佳实践
→ 启用 TLS 1.3 和 HTTP/2 只需要配置变更
阶段 2: TCP + QUIC 双栈
→ CDN 层启用 QUIC (Cloudflare/Fastly 已支持)
→ 通过 Alt-Svc 头部协商 HTTP/3
→ TCP 作为 fallback
阶段 3: QUIC 优先
→ 当 QUIC 生态成熟后,QUIC 作为主要传输
→ TCP 仅作为 fallback
→ 需要负载均衡器和后端全面支持 QUIC
# Nginx 配置: HTTP/2 + HTTP/3 双栈
server {
listen 443 ssl;
listen 443 quic; # QUIC 监听同一端口
http2 on;
ssl_certificate /etc/ssl/cert.pem;
ssl_certificate_key /etc/ssl/key.pem;
# 告诉客户端支持 HTTP/3
add_header Alt-Svc 'h3=":443"; ma=86400';
# QUIC 需要 UDP 443 端口开放
# 确保防火墙规则: iptables -A INPUT -p udp --dport 443 -j ACCEPT
}
3.2 实时游戏
场景特征:
- 高频状态更新(20-60 Hz)
- 延迟极其敏感(<50ms 目标)
- 可以容忍少量丢包(旧状态被新状态覆盖)
- 同时需要可靠通道(登录、聊天、排行榜)
推荐选型:
方案 A: UDP + 应用层可靠性(主流)
用途: 游戏状态同步
✓ 最低延迟,丢包不阻塞
✓ 可以精确控制重传策略
✗ 需要自建序列号、ACK、重传
✗ 需要自建拥塞控制(或不做,在 LAN 场景可以接受)
方案: 状态更新走 UDP(不可靠)
登录/聊天走 TCP(可靠)
方案 B: KCP over UDP(推荐中小团队)
用途: 需要可靠 + 低延迟的混合场景
✓ 比 TCP 更激进的重传(牺牲带宽换延迟)
✓ 现成的库,不需要从零实现
✗ 无拥塞控制(或有限),可能对共享网络不友好
✗ 没有加密
方案 C: QUIC(新兴选择)
用途: 需要加密 + 多流的场景
✓ 多流隔离(游戏状态和聊天互不阻塞)
✓ 连接迁移(WiFi ↔ 4G 不断连)
✓ 内置加密
✗ 用户态协议栈的 CPU 开销
✗ 强制可靠传输(不适合纯不可靠场景)
✗ 加密开销在高 PPS 场景下不可忽视
不推荐: TCP(延迟敏感场景)
✗ Nagle + Delayed ACK 的交互导致额外延迟
✗ 丢包导致队头阻塞
✗ 即使关闭 Nagle(TCP_NODELAY),重传超时仍影响尾延迟
不推荐: SCTP
✗ 客户端(手机/PC)的 NAT 无法穿越
// 游戏中常见的 UDP 双通道模式
// 通道 1: 不可靠通道 — 游戏状态(位置、朝向、血量)
struct game_state_packet {
uint16_t seq; // 序列号(用于检测丢包和乱序,不用于重传)
uint32_t timestamp; // 客户端时间戳
float pos_x, pos_y, pos_z;
float rot_y;
uint8_t health;
uint8_t action_flags;
};
// 丢了就丢了 — 下一帧的状态会覆盖
// 通道 2: 可靠通道 — 关键事件(击杀、道具获取、聊天)
struct reliable_packet {
uint16_t seq; // 序列号
uint16_t ack; // 确认序列号
uint32_t ack_bits; // 最近 32 个包的 ACK 位图
uint8_t type; // 消息类型
uint8_t data[]; // 消息内容
};
// 丢了必须重传 — 这些事件不能跳过
// 两个通道可以复用同一个 UDP socket
// 用 packet 头部的标志位区分3.3 IoT 与传感器网络
场景特征:
- 低带宽、高延迟、间歇连接
- 设备资源受限(内存/CPU/电池)
- 消息小但频繁
- 需要长时间保持"连接"(实际是周期性唤醒)
推荐选型:
首选: MQTT over TCP
✓ 成熟的 IoT 生态(EMQX/Mosquitto/HiveMQ)
✓ QoS 0/1/2 覆盖不同可靠性需求
✓ 低开销的心跳机制(PINGREQ/PINGRESP)
✓ Retained Message 和 Last Will
✓ TCP 可靠传输确保消息不丢
✗ TCP 握手开销(对于极短连接)
✗ TCP 在高丢包网络下性能退化
替代: CoAP over UDP
✓ 更低的协议开销(二进制格式、4 字节头部)
✓ 无连接,适合休眠/唤醒模式
✓ 内置重试和确认(Confirmable/Non-confirmable)
✓ 可用 DTLS 加密
✗ 没有 MQTT 那样的 pub/sub 语义(需要额外中间件)
✗ UDP 可能被某些网络阻止
新兴: MQTT 5.0 over QUIC
✓ 0-RTT 恢复(减少唤醒后的连接开销)
✓ 连接迁移(设备移动场景)
✓ EMQX 5.0 已支持 MQTT over QUIC
✗ 设备端 QUIC 栈的资源开销
✗ 尚不成熟
不推荐: SCTP
✗ IoT 设备的操作系统通常不支持
✗ NAT 穿越问题
3.4 实时音视频(RTC)
场景特征:
- 超低延迟要求(<200ms 端到端)
- 可以容忍少量丢包(编解码器有容错机制)
- 需要 P2P 或 SFU 中转
- 同时需要媒体流(不可靠)和数据通道(可靠/部分可靠)
推荐选型:
标准方案: WebRTC
媒体: SRTP over UDP
✓ 不可靠传输,丢包不重传
✓ NACK 选择性重传(关键帧)
✓ FEC 前向纠错(减少重传需求)
数据: SCTP over DTLS over UDP
✓ 多流 + 消息边界 + 可选有序
✓ PR-SCTP 支持部分可靠
信令: WebSocket over TCP
✓ 可靠的信令交换
自建方案: RTP/RTCP over UDP
用途: 非浏览器场景(直播推流、监控)
✓ 可以精确控制编码参数和传输策略
✓ Jitter Buffer 大小可调
✗ 需要自建 STUN/TURN 穿越 NAT
✗ 需要自建拥塞控制(GCC/NADA/SCReAM)
新兴: WebTransport (QUIC)
用途: 浏览器内的低延迟传输
✓ 同时支持可靠流和不可靠数据报
✓ 不需要 P2P(client-server 模型)
✗ 不支持 P2P(只能 client-server)
✗ 浏览器支持仍在演进
不推荐: TCP
✗ 队头阻塞导致延迟抖动
✗ 重传过时数据浪费带宽
✗ Nagle/Delayed ACK 增加延迟
3.5 微服务 RPC
场景特征:
- 数据中心内部通信(低延迟网络)
- 高 QPS、多连接
- 需要负载均衡和服务发现
- 需要多路复用(一个连接上的多个并发请求)
推荐选型:
首选: gRPC over HTTP/2 (TCP)
✓ 成熟的 RPC 框架生态
✓ Protobuf 高效编码
✓ 四种通信模式(Unary/Server Stream/Client Stream/Bidi)
✓ 丰富的中间件(认证、限流、追踪)
✗ TCP 层队头阻塞
✗ L7 负载均衡需要 HTTP/2 感知
进阶: gRPC over QUIC
✓ 消除 TCP 层队头阻塞
✓ 更快的连接建立
✗ 数据中心内 QUIC 的加密开销可能不必要
✗ QUIC 负载均衡器不如 TCP 成熟
数据中心特定: SCTP
✓ 多流无队头阻塞
✓ 多宿主故障切换(数据中心双上联)
✓ 数据中心没有 NAT 问题
✗ gRPC 不支持 SCTP 传输
✗ 负载均衡器不支持 SCTP
✗ 运维团队不熟悉
不推荐: 裸 UDP
✗ 数据中心 RPC 需要可靠传输
✗ 需要自建整个 RPC 栈
3.6 选型决策矩阵
Web 游戏 IoT 音视频 RPC
TCP (HTTP/2) ★★★ ★ ★★★ ★ ★★★
UDP ★ ★★★ ★★ ★★★ ★
QUIC (HTTP/3) ★★★ ★★ ★★ ★★ ★★
SCTP ✗ ✗ ✗ ★★ ★
KCP/ENet over UDP ✗ ★★★ ★ ✗ ✗
MQTT over TCP ✗ ✗ ★★★ ✗ ✗
★★★ = 首选 ★★ = 可用 ★ = 勉强 ✗ = 不适合
四、决策流程图
面对一个具体场景,可以用以下决策流程做快速判断:
开始
│
├─ 数据能容忍丢失吗?
│ │
│ ├─ 否(必须可靠)
│ │ │
│ │ ├─ 需要公网部署吗?
│ │ │ ├─ 是 → 需要多路复用?
│ │ │ │ ├─ 是 → QUIC (HTTP/3) 或 TCP (HTTP/2)
│ │ │ │ └─ 否 → TCP
│ │ │ │
│ │ │ └─ 否(数据中心/电信)
│ │ │ ├─ 需要多宿主故障切换?
│ │ │ │ ├─ 是 → SCTP
│ │ │ │ └─ 否 → TCP 或 QUIC
│ │ │ └─ 需要多流?
│ │ │ ├─ 是 → SCTP 或 QUIC
│ │ │ └─ 否 → TCP
│ │
│ └─ 是(可以丢失)
│ │
│ ├─ 延迟敏感度?
│ │ ├─ 极高(<50ms, 如游戏)→ UDP + 应用层协议
│ │ ├─ 高(<200ms, 如视频)→ UDP (RTP) 或 WebRTC
│ │ └─ 中(<1s, 如遥测)→ CoAP/UDP 或 MQTT/TCP
│ │
│ └─ 需要浏览器支持?
│ ├─ 是 → WebRTC 或 WebTransport
│ └─ 否 → UDP + 自定义协议
│
└─ 部分可靠(部分数据可丢,部分必须送达)?
│
├─ 浏览器场景 → WebRTC DataChannel (SCTP over DTLS)
├─ 游戏场景 → UDP 双通道(可靠 + 不可靠)
└─ 电信场景 → PR-SCTP
五、性能数据实测
理论分析需要实测验证。以下是在典型环境下的对比数据:
5.1 连接建立延迟实测
# 测试环境:
# 客户端: 北京
# 服务端: 上海 (RTT ≈ 30ms)
# 网络: 公网, 无丢包
# TCP:
hping3 -S -p 443 -c 10 target_ip
# RTT: 30.2ms ± 1.1ms
# 连接建立: 1 RTT = ~30ms
# TCP + TLS 1.3:
# 使用 openssl s_client 测量
openssl s_client -connect target:443 -tls1_3 -brief 2>&1
# Handshake time: ~90ms (3 RTT: SYN + TLS)
# TCP + TLS 1.3 (Session Resumption):
# 第二次连接使用 PSK
openssl s_client -connect target:443 -tls1_3 \
-sess_in session.pem -brief 2>&1
# Handshake time: ~60ms (2 RTT: SYN + TLS PSK)
# QUIC (HTTP/3) — 新连接:
# ~30ms (1 RTT: QUIC + TLS 合并握手)
# QUIC (HTTP/3) — 0-RTT 恢复:
# ~0ms 握手 + 30ms 数据传输5.2 多路复用场景下的队头阻塞
测试条件:
100 个并发请求,每个 10KB 响应
模拟 1% 丢包 (tc netem loss 1%)
结果:
TCP (HTTP/2):
P50 完成时间: 45ms
P99 完成时间: 380ms ← 队头阻塞导致尾延迟飙升
请求完成时间标准差: 95ms
QUIC (HTTP/3):
P50 完成时间: 42ms
P99 完成时间: 120ms ← 流间无队头阻塞
请求完成时间标准差: 28ms
分析:
P50 差异不大(大多数请求不受丢包影响)
P99 差异 3 倍(TCP 的队头阻塞在丢包时急剧恶化)
这意味着: 丢包率越高,QUIC 的优势越明显
# 复现测试
# 模拟 1% 丢包
tc qdisc add dev eth0 root netem loss 1%
# HTTP/2 (TCP) 测试:
h2load -n 1000 -c 10 -m 100 https://target/10k.bin
# req/s, TTFB, total time
# HTTP/3 (QUIC) 测试:
# 使用支持 HTTP/3 的压测工具
# 如 cloudflare/quiche 的 quiche-client
# 清除丢包模拟
tc qdisc del dev eth0 root5.3 弱网环境对比
测试条件: 模拟移动网络 (RTT=100ms, 2% 丢包, 10Mbps 带宽)
tc qdisc add dev eth0 root netem delay 50ms loss 2% rate 10mbit
单个大文件下载 (10MB):
TCP (CUBIC):
完成时间: 12.3s
有效吞吐: 6.5 Mbps
重传率: 3.2%
TCP (BBR):
完成时间: 9.8s
有效吞吐: 8.2 Mbps
重传率: 2.8%
QUIC (默认拥塞控制):
完成时间: 10.1s
有效吞吐: 7.9 Mbps
重传率: 2.9%
连接建立: 比 TCP+TLS 快 100ms
UDP (无拥塞控制, 10Mbps 发送):
完成时间: 8.4s (如果不考虑丢包)
实际到达率: ~9.8 Mbps
丢包率: 2.0%
注意: 无拥塞控制会加剧网络拥塞!
分析:
- BBR 在有丢包的网络中表现明显优于 CUBIC
- QUIC 和 TCP BBR 性能接近,但 QUIC 连接建立更快
- UDP 无拥塞控制看似最快,但在共享网络中会伤害其他流量
六、迁移路径与策略
6.1 从 TCP 迁移到 QUIC
迁移策略: 渐进式双栈
阶段 1: 评估 (1-2 周)
□ 测量当前 TCP 性能基线 (TTFB, P99 延迟, 重传率)
□ 评估 QUIC 库成熟度 (quiche / msquic / ngtcp2)
□ 检查基础设施 QUIC 支持 (CDN, LB, 防火墙)
□ 测试 UDP 443 的可达率
阶段 2: CDN 层启用 (1-2 周)
□ 在 CDN 层开启 HTTP/3 (Cloudflare / Fastly / Akamai)
□ 添加 Alt-Svc 响应头
□ 监控 HTTP/3 使用率和性能指标
□ 保持 TCP 作为完整 fallback
阶段 3: 源站支持 (2-4 周)
□ 源站部署 QUIC 支持 (Nginx / Caddy / H2O)
□ 端到端 QUIC (CDN ↔ 源站)
□ 优化 QUIC 参数 (初始拥塞窗口, 0-RTT 策略)
阶段 4: 优化 (持续)
□ 启用 0-RTT (评估重放攻击风险)
□ 连接迁移 (移动客户端)
□ QUIC 负载均衡 (基于 Connection ID)
□ 监控和告警完善
6.2 从 TCP 迁移到 UDP(游戏/实时场景)
迁移策略: 双通道
原架构:
Client ── TCP ──→ Server
所有通信走一个 TCP 连接
延迟问题: Nagle, HoL, 重传阻塞
目标架构:
Client ── UDP (不可靠) ──→ Server // 状态同步
Client ── TCP (可靠) ──→ Server // 关键事件
迁移步骤:
1. 识别消息类型
可靠消息: 登录、道具获取、聊天、排行榜
不可靠消息: 位置更新、动画状态、环境音效
2. 设计 UDP 消息格式
头部: seq(2B) + ack(2B) + type(1B) + flags(1B)
可靠消息: 在 UDP 上实现 ACK + 重传
不可靠消息: 只发不管
3. 或使用现成框架
KCP: 可靠 UDP, 配置灵活
ENet: 可靠/不可靠双通道, 有连接管理
GameNetworkingSockets (Valve): 加密 + 可靠 UDP
6.3 什么时候不要迁移
迁移有成本,不是所有场景都值得:
不值得迁移到 QUIC 的场景:
✗ 内部数据中心的 RPC
→ RTT <1ms, 连接建立延迟不重要
→ TCP 连接池消除了握手开销
→ 加密开销在内网中可能不需要(mTLS 另论)
✗ 长连接、低频请求
→ 连接建立只发生一次,QUIC 优势可忽略
→ 如 WebSocket 长连接、数据库连接池
✗ 吞吐量密集型传输
→ QUIC 用户态协议栈的吞吐上限 < TCP
→ 大文件传输、数据库备份、流媒体推流
不值得迁移到 UDP 的场景:
✗ 数据不能丢失的场景
→ 金融交易、数据库复制、文件同步
→ 在 UDP 上重建可靠传输 = 重造一个不如 TCP 的轮子
✗ 开发团队不熟悉网络编程
→ UDP 编程的坑(分片、NAT、丢包处理)远多于 TCP
→ TCP 的错误模式更容易理解和调试
✗ 不需要低延迟的场景
→ 如果 P99 延迟 200ms 可以接受,TCP 通常够用
→ UDP 的复杂性只在延迟敏感场景下才值得
七、混合架构模式
实际系统很少只用一种传输协议。理解常见的混合架构模式有助于做出更好的选型:
7.1 Web 应用典型架构
用户 ──[QUIC/HTTP3]──→ CDN ──[TCP/HTTP2]──→ LB ──[TCP/gRPC]──→ 微服务
│
┌─── TCP (Redis) │
├─── TCP (PostgreSQL) │
└─── TCP (Kafka) │
CDN 边缘用 QUIC 获取连接建立优势;CDN 到源站用 TCP 长连接(连接已建立,握手延迟不重要);微服务间用 gRPC/TCP(内网低延迟,生态成熟)。
7.2 游戏服务典型架构
游戏客户端
├── UDP (状态同步, 20-60 fps) ──→ Game Server
├── TCP (聊天/好友/商店) ──→ Social Server
└── HTTPS (登录/支付) ──→ API Gateway ──→ Auth/Payment
Game Server
├── UDP (服务器间状态同步) ──→ 其他 Game Server
└── TCP (gRPC, 存档/匹配) ──→ Backend Services
7.3 IoT 平台典型架构
传感器设备
├── MQTT over TCP (遥测数据) ──→ MQTT Broker (EMQX)
├── CoAP over UDP (约束设备) ──→ CoAP Gateway ─┐
└── HTTPS (固件更新) ──→ OTA Server │
↓
消息队列 (Kafka/TCP)
↓
数据处理 (gRPC/TCP)
7.4 实时通信平台典型架构
浏览器/客户端
├── WebSocket/TCP (信令) ──→ Signaling Server
├── SRTP/UDP (音视频) ──→ SFU / TURN
├── SCTP/DTLS/UDP (数据通道) ──→ P2P / SFU
└── HTTPS (REST API) ──→ API Server
SFU (Selective Forwarding Unit)
├── SRTP/UDP (媒体转发) ──→ 其他 SFU
└── gRPC/TCP (控制面) ──→ Control Plane
八、协议特性速查表
┌───────────────┬──────────┬──────────┬──────────┬──────────┐
│ 特性 │ TCP │ UDP │ QUIC │ SCTP │
├───────────────┼──────────┼──────────┼──────────┼──────────┤
│ RFC │ 793 │ 768 │ 9000 │ 9260 │
│ 年份 │ 1981 │ 1980 │ 2021 │ 2000 │
│ 层级 │ 传输层 │ 传输层 │ 应用层* │ 传输层 │
│ 协议号/端口 │ Proto 6 │ Proto 17 │ UDP上 │ Proto132 │
├───────────────┼──────────┼──────────┼──────────┼──────────┤
│ 面向连接 │ 是 │ 否 │ 是 │ 是 │
│ 可靠传输 │ 是 │ 否 │ 是 │ 是/部分 │
│ 有序交付 │ 全局 │ 否 │ 流内 │ 流内 │
│ 消息边界 │ 否 │ 是 │ 流/DG │ 是 │
│ 多流 │ 否 │ N/A │ 是 │ 是 │
│ 多宿主 │ 否 │ N/A │ 迁移 │ 是 │
├───────────────┼──────────┼──────────┼──────────┼──────────┤
│ 拥塞控制 │ 必须 │ 无 │ 必须 │ 必须 │
│ 流量控制 │ 窗口 │ 无 │ 窗口 │ 窗口 │
│ 加密 │ 可选TLS │ 可选DTLS │ 内置TLS │ 可选DTLS │
├───────────────┼──────────┼──────────┼──────────┼──────────┤
│ 握手RTT │ 1(+TLS) │ 0 │ 1(含TLS) │ 2 │
│ 0-RTT恢复 │ TFO/PSK │ N/A │ 是 │ 否 │
│ 头部开销 │ 20-60B │ 8B │ ~20B │ 16B+ │
├───────────────┼──────────┼──────────┼──────────┼──────────┤
│ NAT穿越 │ 好 │ 好 │ 好 │ 差 │
│ 内核/用户态 │ 内核 │ 内核 │ 用户态 │ 内核 │
│ 浏览器支持 │ 是 │ 否** │ 是 │ 否*** │
│ 生态成熟度 │ 最高 │ 高 │ 增长中 │ 电信专用 │
└───────────────┴──────────┴──────────┴──────────┴──────────┘
* QUIC 从 OS 角度看是 UDP,从功能上是传输层
** WebRTC 底层使用 UDP,但浏览器 JS 无法直接发 UDP
*** WebRTC DataChannel 使用 SCTP over DTLS over UDP
九、结论
传输协议选型不是”谁最先进”的问题,而是”谁最适合你的场景、团队和基础设施”的问题。
几个核心判断:
TCP 仍然是默认选择。 除非你有明确的理由(延迟敏感、需要多流、需要连接迁移),否则 TCP 是风险最低、成本最低的选择。它的生态成熟度和部署可靠性是其他协议无法比拟的。
QUIC 是 Web 服务的未来方向。 如果你做 Web 服务,TCP → QUIC 的迁移是大势所趋。但”渐进式双栈”比”激进替换”更安全——先在 CDN 层启用,再扩展到源站。
UDP 是延迟敏感场景的正确选择。 游戏、实时音视频、传感器遥测——这些场景的核心需求是”尽快送达,过时的数据不如不送”。UDP 给你最大的控制自由度,但也要求最高的工程能力。
SCTP 是电信/数据中心的专用选择。 在不需要穿越 NAT 的环境中,SCTP 的多宿主和多流特性确实优于 TCP。但除了电信信令面和 WebRTC DataChannel,它几乎没有其他生存空间。
混合架构是常态。 实际系统几乎都用多种传输协议——CDN 用 QUIC,内部 RPC 用 TCP,游戏状态用 UDP。不要试图用一种协议解决所有问题。
部署可行性 > 技术优劣。 SCTP 的失败证明了这一点——技术上最优的协议如果无法穿越 NAT,就无法在公网使用。做选型时,永远把”能不能部署”放在”性能好不好”前面。
最终,传输协议的选择应该基于对场景的精确分析,而不是对协议的主观偏好。用数据说话——测量你的延迟、丢包率、吞吐需求和部署约束,然后让数据告诉你答案。
同主题继续阅读
把当前热点继续串成多页阅读,而不是停在单篇消费。
【网络工程】QUIC 生态与工程部署:从实验到生产
QUIC 已经不是实验性协议——HTTP/3 标准化后,CDN、浏览器和主流服务端框架都在推进 QUIC 支持。本文从工程视角对比主流 QUIC 库的成熟度和性能特征,讲解 CDN/负载均衡器的 QUIC 适配方案、从 TCP 迁移到 QUIC 的渐进路径、QUIC 调试工具链,以及生产环境的部署陷阱和性能调优实践。
【网络工程】可靠 UDP 框架:KCP、ENet 与 QUIC 的设计对比
TCP 的可靠传输是一种固定策略——全量有序、丢包即重传、拥塞窗口统一管理。但很多场景需要'可定制的可靠性':游戏要低延迟重传、视频要部分可靠、RPC 要多路复用无队头阻塞。本文深入对比 KCP、ENet、QUIC 三个在 UDP 上构建可靠传输的框架,剖析它们的 ARQ 策略、流控设计和工程取舍。
【网络工程】SCTP 协议工程:多宿主与多流的传输层替代
SCTP 在协议层面解决了 TCP 的两个结构性缺陷——单路径和单流——提供原生的多宿主故障切换和多流无队头阻塞传输。它在电信核心网中广泛部署,但在公网上几乎不可用。本文剖析 SCTP 的协议设计、四次握手安全机制、多宿主工程实践,以及它为何在部署竞争中输给了 QUIC。
【QUIC 协议拆解】QUIC 协议拆解(上):为什么 TCP 改不动了
打开一个网页要握手几次?TCP 三次 + TLS 一次 = 至少 2 RTT。QUIC 说:我一次搞定,重连甚至 0 次。不是 TCP 不够好,是它的基因决定了它改不动。