环境搭建: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
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/
--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
-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
6. 本章知识体系
下面这张图,把本章的环境搭建逻辑串起来了。你跟着箭头走一遍,就知道先做什么、后做什么。
环境搭好之后,下一步就是跑测试了。不过别急,先确认几个点:
- 内核参数是否已经生效(
sysctl net.core.rmem_max检查) - QUIC 客户端能否正常连接(
quiche-client或http_client跑一次) - qperf 服务端和客户端是否在同一网段(避免跨网段干扰)
这些基础打牢了,后面的吞吐测试才有意义。不然你测出来的数据,到底是 QUIC 的问题,还是环境的问题,根本分不清。