环境搭建:Linux内核参数调优、安装quiche/lsquic客户端、编译msquic库、iperf3与qperf对比

说实话,QUIC 的测试环境搭建,比 TCP 要麻烦不少。TCP 测试你装个 iperf3 基本就完事了,但 QUIC 不一样——它依赖内核的 UDP 支持,而且不同 QUIC 实现库的编译方式天差地别。我最早踩坑的时候,光编译 msquic 就折腾了大半天,后来才发现是内核参数没调好。

这一章,咱们就把环境彻底搞定。我会按实际操作的顺序来:先调内核,再装客户端,最后对比测试工具。你跟着走一遍,后面跑测试就不会卡壳了。

1. Linux 内核参数调优

QUIC 跑在 UDP 上,所以内核里跟 UDP 相关的参数都得调。我个人的习惯是,先看当前值,再针对性修改。

1.1 查看当前 UDP 缓冲区

# 查看当前 UDP 读写缓冲区大小(字节)
sysctl net.core.rmem_default
sysctl net.core.rmem_max
sysctl net.core.wmem_default
sysctl net.core.wmem_max

# 典型输出(单位:字节)
net.core.rmem_default = 212992
net.core.rmem_max = 212992
net.core.wmem_default = 212992
net.core.wmem_max = 212992

你看,默认只有 208KB。这个值对于 TCP 来说够用,但 QUIC 的拥塞控制、丢包重传、多路复用都在用户态处理,内核缓冲区太小会导致频繁的系统调用,吞吐直接腰斩。我在一次 10Gbps 测试中,就因为没调这个,qperf 死活跑不到 2Gbps。

1.2 调大缓冲区

我建议直接改成 16MB,对于大部分 10Gbps 以内的链路都够用。

# 临时生效(重启后丢失)
sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.wmem_max=16777216
sysctl -w net.core.rmem_default=16777216
sysctl -w net.core.wmem_default=16777216

# 永久生效
echo 'net.core.rmem_max=16777216' >> /etc/sysctl.conf
echo 'net.core.wmem_max=16777216' >> /etc/sysctl.conf
echo 'net.core.rmem_default=16777216' >> /etc/sysctl.conf
echo 'net.core.wmem_default=16777216' >> /etc/sysctl.conf
sysctl -p
小提示:如果你用的是 25Gbps 或更高速的网卡,建议把缓冲区调到 64MB。不过要注意,调太大可能会占用过多内存,尤其是多连接场景下。

1.3 其他关键参数

参数名 推荐值 说明
net.core.netdev_max_backlog 50000 网卡接收队列最大长度,高吞吐下建议调大
net.ipv4.udp_mem "262144 327680 393216" UDP 内存压力阈值(单位:页),默认偏小
net.ipv4.udp_rmem_min 16384 UDP 最小接收缓冲区,防止低流量时过度收缩
net.ipv4.udp_wmem_min 16384 UDP 最小发送缓冲区
net.core.somaxconn 65535 listen 队列长度,QUIC 连接多时有用
注意:修改 udp_mem 时,三个值分别代表:最低阈值、压力阈值、最大阈值。单位是内存页(通常 4KB)。不要直接抄网上的值,要根据你的物理内存来算。我曾经在一台 64GB 的机器上设了 "1048576 2097152 3145728",结果内存占用飙到 12GB,吓我一跳。

2. 安装 quiche 客户端

quiche 是 Cloudflare 开源的 QUIC 实现,用 Rust 写的。它的客户端工具叫 quiche-client,可以用来发起 HTTP/3 请求,也能做简单的吞吐测试。

2.1 编译安装

# 安装 Rust 工具链(如果没装)
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
source $HOME/.cargo/env

# 克隆 quiche 仓库
git clone --recursive https://github.com/cloudflare/quiche.git
cd quiche

# 编译客户端(需要联网下载依赖)
cargo build --release --examples

# 编译完成后,客户端在 target/release/examples/ 下
ls target/release/examples/quiche-client

编译过程可能会比较慢,尤其是第一次,因为要下载很多 Rust 依赖包。我建议用 --jobs 4 限制并行编译任务数,避免把 CPU 跑满导致系统卡死。

2.2 基本使用

# 发起 HTTP/3 请求
./target/release/examples/quiche-client https://example.com

# 指定网卡和端口(用于测试)
./target/release/examples/quiche-client \
  --wire-version 1 \
  --no-verify \
  https://192.168.1.100:4433/
小提示:quiche 默认会验证证书,测试环境可以用 --no-verify 跳过。另外,--wire-version 1 指定使用 QUIC v1,避免兼容性问题。

3. 安装 lsquic 客户端

lsquic 是 LiteSpeed 开源的 QUIC 实现,用 C 语言写的。它的客户端工具叫 http_client,功能比 quiche 更丰富,支持多线程和自定义拥塞控制算法。

3.1 编译安装

# 安装依赖(Ubuntu/Debian)
apt-get install build-essential cmake libssl-dev zlib1g-dev

# 克隆 lsquic 仓库
git clone https://github.com/litespeedtech/lsquic.git
cd lsquic

# 初始化子模块
git submodule init
git submodule update

# 编译
cmake -B build -DCMAKE_BUILD_TYPE=Release
cmake --build build

# 编译完成后,客户端在 build/bin/ 下
ls build/bin/http_client

3.2 基本使用

# 发起 HTTP/3 请求
./build/bin/http_client -H https://example.com

# 指定并发连接数(用于吞吐测试)
./build/bin/http_client \
  -H https://192.168.1.100:4433/ \
  -s /path/to/10MB.file \
  -n 4

-n 4 表示 4 个并发连接,-s 指定下载的文件路径。lsquic 的客户端输出很详细,会显示每个连接的速度和总吞吐。

4. 编译 msquic 库

msquic 是微软开源的 QUIC 实现,主要用于 Windows,但也支持 Linux。它的特点是性能优化做得很好,尤其是多核场景下。我一般在 Linux 上编译它来做服务端测试。

4.1 编译步骤

# 安装依赖
apt-get install cmake gcc g++ libssl-dev libnuma-dev

# 克隆 msquic 仓库
git clone --recursive https://github.com/microsoft/msquic.git
cd msquic

# 配置编译(使用 OpenSSL)
cmake -B build \
  -DCMAKE_BUILD_TYPE=Release \
  -DQUIC_TLS=openssl \
  -DQUIC_ENABLE_LOGGING=OFF

# 编译
cmake --build build --parallel

# 编译完成后,库文件在 build/bin/Release/ 下
ls build/bin/Release/libmsquic.so
注意:msquic 默认使用 Schannel(Windows 的 TLS 实现),在 Linux 上必须指定 -DQUIC_TLS=openssl。另外,QUIC_ENABLE_LOGGING 建议关掉,否则日志会严重影响性能。我一开始没关,测试时发现吞吐只有正常值的 60%,排查了半天才发现是日志 I/O 拖了后腿。

4.2 验证编译结果

# 查看库文件信息
ldd build/bin/Release/libmsquic.so

# 运行自带的测试工具
./build/bin/Release/quicinterop -server -cert_file:/path/to/cert.pem -key_file:/path/to/key.pem

5. iperf3 与 qperf 对比

说到测试工具,iperf3 大家都很熟了,但它只支持 TCP 和 UDP,不支持 QUIC。qperf 是专门为 QUIC 设计的性能测试工具,由 Google 的 QUIC 团队维护。

5.1 工具对比

特性 iperf3 qperf
协议支持 TCP、UDP、SCTP QUIC v1、v2
拥塞控制 内核态(CUBIC、BBR 等) 用户态(CUBIC、BBR、NewReno 等)
多流支持 单流(-P 参数模拟多连接) 原生多流(-u 参数)
0-RTT 测试 不支持 支持(-0 参数)
丢包模拟 需配合 netem 内置丢包模拟(-l 参数)
安装难度 简单(apt install iperf3) 中等(需编译)

5.2 安装 qperf

# 克隆 qperf 仓库
git clone https://github.com/ekr/qperf.git
cd qperf

# 编译
make

# 编译完成后,生成 qperf 可执行文件
ls qperf

5.3 基本使用

服务端(先启动):

./qperf -s -p 4433

客户端(发起测试):

# 默认测试(单流,10 秒)
./qperf -c 192.168.1.100 -p 4433 -t 10

# 多流测试(4 条流)
./qperf -c 192.168.1.100 -p 4433 -u 4 -t 10

# 0-RTT 测试
./qperf -c 192.168.1.100 -p 4433 -0 -t 10
核心区别:iperf3 测的是内核协议栈的性能,qperf 测的是用户态 QUIC 实现的性能。两者结果不能直接对比,但可以互相印证。我一般先用 iperf3 测 UDP 打底,再用 qperf 测 QUIC,看 QUIC 的额外开销有多大。

6. 本章知识体系

下面这张图,把本章的环境搭建逻辑串起来了。你跟着箭头走一遍,就知道先做什么、后做什么。

QUIC 测试环境搭建流程 QUIC 测试环境搭建流程 1. Linux 内核参数调优 2a. 安装 quiche 2b. 安装 lsquic 2c. 编译 msquic 3a. iperf3(TCP/UDP 基准) 3b. qperf(QUIC 测试) 4. 运行测试,验证环境 💡 说明:内核调优是基础,三个 QUIC 实现可以选装,工具对比建议都跑一遍。 iperf3 测 UDP 基准,qperf 测 QUIC 实际性能,两者结合才能定位瓶颈。

环境搭好之后,下一步就是跑测试了。不过别急,先确认几个点:

  • 内核参数是否已经生效(sysctl net.core.rmem_max 检查)
  • QUIC 客户端能否正常连接(quiche-client 或 http_client 跑一次)
  • qperf 服务端和客户端是否在同一网段(避免跨网段干扰)

这些基础打牢了,后面的吞吐测试才有意义。不然你测出来的数据,到底是 QUIC 的问题,还是环境的问题,根本分不清。