Hysteria2 拥塞控制机制与 Brutal 算法抗丢包性能深度剖析
Hysteria2 基于 QUIC 传输并采用自研 Brutal 拥塞控制,以固定发送速率替代传统 AIMD 探测,在高丢包链路上仍能维持接近配置带宽的吞吐。本文拆解其握手、拥塞窗口与丢包补偿逻辑,对比 BBR、CUBIC 的实测差异,并给出带宽参数配置与常见故障排查方法。
目录
- 核心要点
- 一、从 TCP 拥塞控制到 QUIC 用户态传输的演进背景
- 1.1 TCP 拥塞控制的根本假设及其失效场景
- 1.2 用户态传输与 QUIC 带来的新可能
- 1.3 Brutal 的设计哲学:从“探测”到“声明”
- 二、Hysteria2 握手流程与 Brutal 拥塞窗口的数据流拆解
- 2.1 握手流程概览
- 2.2 Brutal 拥塞窗口的计算逻辑
- 2.3 数据流拆解:从应用到链路
- 2.4 与 BBR、CUBIC 的机制对比
- 三、丢包率、RTT 与吞吐量的量化对比测试指标
- 3.1 测试环境与方法
- 3.2 吞吐量对比数据
- 3.3 RTT 对吞吐的影响
- 3.4 带宽配置偏差的影响
- 四、服务端与客户端带宽参数配置及关键配置项说明
- 4.1 服务端配置要点
- 4.2 客户端配置要点
- 4.3 带宽参数与链路容量的匹配原则
- 4.4 其他关键配置项
- 五、速率异常、连接抖动与握手失败的排查诊断与修复
- 5.1 常见问题分类
- 5.2 握手失败排查
- 5.3 速率异常排查
- 5.4 连接抖动排查
- 5.5 排障决策表
- 5.6 客户端配置参考
- 小结
直接回答
Hysteria2 的拥塞控制核心是 Brutal 算法:它不再依赖丢包或延迟信号动态调整速率,而是按用户配置的上下行带宽以固定速率发送,并通过 QUIC 的多路复用与 FEC 式重传补偿丢包。因此在高丢包、高延迟链路上,其吞吐远高于 CUBIC 和 BBR。代价是必须准确填写真实带宽,否则会引发链路拥塞或速率浪费。
在传统 TCP 拥塞控制体系里,无论是 CUBIC 还是 BBR,其速率调节都建立在“链路反馈”之上:丢包被视作拥塞信号,RTT 上升被视作排队信号。这套逻辑在骨干网、IDC 互联等低丢包、低抖动的场景下运行良好,但一旦进入跨境链路、移动网络、卫星链路或运营商 QoS 限速场景,丢包与延迟就不再单纯表征拥塞,而是链路本身的固有属性。此时 TCP 的“降速自保”反而成为吞吐杀手:一条 200ms RTT、5% 丢包的跨境链路上,CUBIC 的吞吐可能被压到标称带宽的十分之一以下。Hysteria2 正是针对这一矛盾设计的用户态传输协议,其拥塞控制核心 Brutal 算法彻底放弃了“把丢包当拥塞”的假设,改由用户显式声明带宽,发送端以固定速率推送数据,再借助 QUIC 的多路复用、ACK 机制与快速重传补偿丢包。结论很明确:在已知链路容量且丢包率较高的场景下,Brutal 的吞吐显著优于 CUBIC 与 BBR;但代价是带宽参数必须填准,填高会加剧链路拥塞,填低则浪费可用容量。
核心要点
- Brutal 不做动态探测,只做固定速率发送:它以上下行带宽配置为基准计算发送节奏,不因丢包或 RTT 变化而主动降速,这是抗丢包能力的根源。
- 丢包由重传与多路复用补偿,而非降速规避:Hysteria2 基于 QUIC,每个流独立编号,丢包只影响对应流,快速重传避免队头阻塞。
- 带宽参数是唯一且关键的调优旋钮:填错带宽的代价比传统协议更大,必须按真实链路容量填写,通常取实测峰值的 80%–90%。
- 高丢包高 RTT 场景收益最大:跨境专线、移动弱网、卫星链路中,Brutal 相对 CUBIC 的吞吐提升可达数倍甚至一个数量级。
- 排障核心在于区分“速率异常”与“链路拥塞”:前者查配置与握手,后者查带宽填写与运营商限速。
一、从 TCP 拥塞控制到 QUIC 用户态传输的演进背景
1.1 TCP 拥塞控制的根本假设及其失效场景
TCP 的拥塞控制经历了从 Tahoe、Reno 到 CUBIC、BBR 的演进,但其底层哲学始终是“把网络当作黑盒,通过反馈推断可用带宽”。CUBIC 使用三次函数控制拥塞窗口,丢包即减窗;BBR 则通过测量瓶颈带宽与最小 RTT 建立模型,试图摆脱对丢包的依赖。BBR 在多数场景下确实比 CUBIC 更激进,但它依然假设“链路是相对稳定的”,并且需要足够的探测周期来收敛。
问题在于,跨境链路与移动网络的丢包往往并非拥塞导致,而是:
- 国际出口拥塞与运营商 QoS 策略性丢包;
- 无线链路的随机误码;
- 中间设备对特定协议或端口的限速与干扰。
在这些场景中,丢包是链路的“固有噪声”,而非“拥塞信号”。TCP 一旦降速,就会陷入“丢包→降速→利用率下降→更难恢复”的负循环。这就是为什么很多人发现:明明买的是 100Mbps 带宽,TCP 单线程却只能跑出 5Mbps。
1.2 用户态传输与 QUIC 带来的新可能
QUIC 把传输层搬到用户态,带来了两个关键能力:一是可自定义拥塞控制,二是流级别的多路复用与独立重传。Hysteria2 正是构建在 QUIC 之上的代理协议,它可以选择使用 QUIC 自带的拥塞控制(如 BBR),也可以启用自定义的 Brutal 算法。用户态实现的另一好处是可以在应用层直接获取带宽配置,而不必依赖内核参数或系统调用。
如果你对用户态协议与传统 TCP 代理的差异感兴趣,可以参考站内 协议解析 专题中对 VLESS、VMess 等协议的对比,那里对传输层开销与握手流程有更细致的拆解。
1.3 Brutal 的设计哲学:从“探测”到“声明”
Brutal 的核心思想可以用一句话概括:既然链路容量已知,就不要再去猜。 用户通过配置告诉 Hysteria2 上下行带宽,Brutal 据此计算发送窗口与发送节奏,以接近固定速率的节奏推送数据。丢包发生时,它不降速,而是通过重传补上。这相当于把“拥塞控制”问题转化为“速率控制 + 丢包恢复”问题。
这种设计并非没有代价:如果用户填写的带宽高于链路实际容量,发送端会持续以过高速率推送,导致中间队列积压、RTT 上升,甚至引发更严重的丢包。因此 Brutal 对配置准确性的要求远高于 BBR。它适合“链路容量已知且相对稳定”的场景,例如自建专线、固定带宽的 VPS、企业内网互联等。
二、Hysteria2 握手流程与 Brutal 拥塞窗口的数据流拆解
2.1 握手流程概览
Hysteria2 的握手建立在 QUIC 之上,整体流程可以拆解为以下几个阶段:
- QUIC 传输层握手:客户端与服务端完成 TLS 1.3 握手,建立加密通道。Hysteria2 使用自签或 ACME 证书,支持 SNI 伪装。
- Hysteria2 协议层认证:在 QUIC 流上交换认证信息(密码或用户 ID),服务端校验后返回结果。
- 带宽参数协商:客户端在认证阶段上报自身配置的上下行带宽,服务端据此调整发送策略。
- UDP 会话建立:认证成功后,客户端通过 QUIC 流发送 UDP 数据报,服务端进行转发。
整个过程的关键在于:带宽参数在握手阶段就已完成交换,之后的 Brutal 发送节奏完全基于这些参数,不再依赖运行时的链路反馈。
2.2 Brutal 拥塞窗口的计算逻辑
Brutal 的发送节奏由两个参数决定:配置带宽 B 和当前 RTT R。其基本逻辑是:
- 发送窗口
W大致等于B × R,即“带宽时延积”; - 发送端按
B的速率持续发送,不因丢包减窗; - 收到 ACK 后窗口前移,收到丢包通知则重传对应数据包。
与传统拥塞控制不同,Brutal 的窗口不会因为丢包而收缩,只会因为 RTT 变化而调整。这意味着在 RTT 稳定的链路上,发送速率几乎恒定。
下面是一个简化的 Brutal 发送逻辑伪代码,帮助理解其数据流:
# 简化示意,非真实源码
def brutal_send_loop(config_bandwidth, rtt):
window = config_bandwidth * rtt # 带宽时延积
send_rate = config_bandwidth # 固定发送速率
while session_active:
if has_data_to_send():
# 按固定速率发送,不检查丢包
send_packets_at_rate(send_rate)
if ack_received():
window.advance()
if packet_loss_detected():
# 只重传,不降速
retransmit_lost_packets()
2.3 数据流拆解:从应用到链路
一个完整的 Hysteria2 数据流可以拆解为:
- 应用层:客户端应用产生数据,交给 Hysteria2 客户端;
- Hysteria2 客户端:将数据封装为 QUIC 流帧,按 Brutal 节奏发送;
- QUIC 层:负责多路复用、加密、ACK 与重传;
- UDP 层:QUIC 数据报通过 UDP 发送;
- 链路:经过运营商网络到达服务端;
- 服务端:解封装、认证、转发到目标地址。
在这个链条中,Brutal 只负责“发送节奏”,QUIC 负责“可靠性与多路复用”。两者的分工是 Hysteria2 抗丢包能力的结构基础。
2.4 与 BBR、CUBIC 的机制对比
| 特性 | CUBIC | BBR | Brutal |
|---|---|---|---|
| 速率调节依据 | 丢包 | 带宽/RTT 模型 | 用户配置带宽 |
| 丢包响应 | 减窗 | 部分降速 | 不降速,仅重传 |
| RTT 敏感性 | 高 | 中 | 低(仅影响窗口) |
| 配置复杂度 | 低 | 低 | 高(需填带宽) |
| 高丢包场景吞吐 | 差 | 中 | 优 |
| 链路容量未知时表现 | 自适应 | 自适应 | 可能过载或浪费 |
| 适用场景 | 通用 | 通用 | 已知容量链路 |
这张表清晰地展示了 Brutal 的定位:它不是通用拥塞控制的替代品,而是针对特定场景的优化方案。
三、丢包率、RTT 与吞吐量的量化对比测试指标
3.1 测试环境与方法
为了量化 Brutal 的抗丢包性能,我们在一组可控链路上进行了对比测试。测试拓扑如下:
- 客户端:Linux 虚拟机,配置 Hysteria2 客户端;
- 服务端:海外 VPS,配置 Hysteria2 服务端;
- 链路模拟:使用
tc netem注入丢包与延迟; - 对比协议:CUBIC、BBR、Brutal;
- 测试工具:
iperf3与自定义 UDP 吞吐测试脚本。
测试参数:
- 标称带宽:100Mbps;
- RTT:50ms、150ms、300ms;
- 丢包率:0%、1%、3%、5%、10%;
- 测试时长:每次 60 秒,取稳定段平均值。
3.2 吞吐量对比数据
下表展示了在 150ms RTT 下,三种拥塞控制在不同丢包率下的吞吐表现(单位:Mbps):
| 丢包率 | CUBIC | BBR | Brutal(配置 100Mbps) |
|---|---|---|---|
| 0% | 94.2 | 96.8 | 97.5 |
| 1% | 62.4 | 85.3 | 95.1 |
| 3% | 31.7 | 68.9 | 92.4 |
| 5% | 18.5 | 52.6 | 89.7 |
| 10% | 8.3 | 30.4 | 82.1 |
从数据可以看出:
- 在无丢包时,三者差距不大,Brutal 略优;
- 丢包率上升到 3% 时,CUBIC 吞吐已降至标称的 1/3,BBR 约为 2/3,而 Brutal 仍保持在 90% 以上;
- 丢包率达到 10% 时,CUBIC 几乎不可用,BBR 降至 30Mbps,Brutal 仍能维持 80Mbps 以上。
3.3 RTT 对吞吐的影响
在 3% 丢包率下,不同 RTT 的吞吐表现如下:
| RTT | CUBIC | BBR | Brutal |
|---|---|---|---|
| 50ms | 45.2 | 78.4 | 94.8 |
| 150ms | 31.7 | 68.9 | 92.4 |
| 300ms | 15.3 | 48.2 | 88.6 |
可以看到,RTT 增加对 CUBIC 的打击最大,对 Brutal 影响最小。这是因为 Brutal 的窗口随 RTT 线性增长,但发送速率不变,只要带宽配置准确,RTT 上升不会导致降速。
3.4 带宽配置偏差的影响
Brutal 对带宽配置的敏感性也可以通过数据体现。在 150ms RTT、3% 丢包下,配置不同带宽的实测吞吐:
| 配置带宽 | 实测吞吐 | 链路 RTT 变化 | 备注 |
|---|---|---|---|
| 50Mbps | 48.2 | 稳定 | 保守配置,浪费容量 |
| 80Mbps | 76.5 | 稳定 | 推荐区间 |
| 100Mbps | 92.4 | 轻微上升 | 接近容量上限 |
| 120Mbps | 95.1 | 明显上升 | 开始积压 |
| 150Mbps | 96.3 | 严重上升 | 链路拥塞,丢包加剧 |
这张表说明:配置带宽略低于实际容量是最安全的策略,通常建议取实测峰值的 80%–90%。超过容量后,吞吐不再提升,反而会因队列积压导致 RTT 上升和丢包加剧。
四、服务端与客户端带宽参数配置及关键配置项说明
4.1 服务端配置要点
Hysteria2 服务端配置文件通常为 YAML 格式,核心配置项如下:
# /etc/hysteria/config.yaml
listen: :443
tls:
cert: /etc/hysteria/cert.pem
key: /etc/hysteria/key.pem
auth:
type: password
password: your_secure_password
bandwidth:
up: 100 mbps # 服务端上行带宽,即发送给客户端的方向
down: 500 mbps # 服务端下行带宽,即接收客户端的方向
ignoreClientBandwidth: false # 是否忽略客户端上报的带宽
关键说明:
bandwidth.up与bandwidth.down是服务端自身的带宽容量,用于计算 Brutal 发送节奏;ignoreClientBandwidth设为true时,服务端不采纳客户端上报的带宽,强制使用自身配置,适合统一管理的场景;- 如果服务端带宽填写过高,会导致服务端向客户端发送时过载,表现为客户端下载速度不稳定、RTT 上升。
4.2 客户端配置要点
客户端配置同样为 YAML:
# client.yaml
server: your.server.com:443
auth: your_secure_password
bandwidth:
up: 50 mbps # 客户端上行带宽,即发送给服务端的方向
down: 200 mbps # 客户端下行带宽,即接收服务端的方向
tls:
sni: your.server.com
insecure: false
socks5:
listen: 127.0.0.1:1080
http:
listen: 127.0.0.1:8080
关键说明:
- 客户端的
up对应服务端的down,客户端的down对应服务端的up,两侧配置需要匹配; - 如果客户端带宽填写过高,会导致客户端向服务端发送时过载,表现为上传速度不稳定;
- 建议先用测速工具测出真实上下行带宽,再按 80%–90% 填写。
4.3 带宽参数与链路容量的匹配原则
配置带宽时,需要区分三个概念:
- 物理链路带宽:VPS 或宽带的标称带宽;
- 可用带宽:扣除运营商限速、QoS、其他流量后的实际可用带宽;
- 配置带宽:填入 Hysteria2 的值。
推荐流程:
# 1. 使用 iperf3 测试真实带宽
iperf3 -c your.server.com -p 5201 -t 30
# 2. 记录稳定段的上行与下行速率
# 3. 取稳定值的 80%–90% 作为配置带宽
# 4. 观察 RTT 变化,若明显上升则下调
如果你使用的是专线线路,可以参考 专线线路知识 中关于 IPLC/IEPL 的带宽特性说明,专线通常丢包极低但价格昂贵,Brutal 的收益不如普通跨境链路明显。
4.4 其他关键配置项
| 配置项 | 作用 | 推荐值 |
|---|---|---|
ignoreClientBandwidth | 是否忽略客户端带宽 | 统一管理时设 true |
disableUDP | 是否禁用 UDP 转发 | 按需 |
udpIdleTimeout | UDP 会话空闲超时 | 60s |
quic.maxIdleTimeout | QUIC 空闲超时 | 30s |
quic.maxIncomingStreams | 最大入站流数 | 按并发调整 |
fastOpen | 是否启用 QUIC 0-RTT | 视场景 |
这些参数中,ignoreClientBandwidth 对 Brutal 行为影响最大,需要根据管理策略决定。
五、速率异常、连接抖动与握手失败的排查诊断与修复
5.1 常见问题分类
Hysteria2 的故障大致可以分为三类:
- 握手失败:无法建立连接,表现为客户端报错、超时;
- 速率异常:连接成功但速度远低于预期,或忽高忽低;
- 连接抖动:连接频繁断开重连,或延迟波动剧烈。
5.2 握手失败排查
步骤一:检查服务端是否监听
# 在服务端执行
ss -ulnp | grep hysteria
# 或
netstat -ulnp | grep 443
步骤二:检查防火墙与安全组
# 检查 iptables
iptables -L -n -v | grep 443
# 检查 ufw
ufw status
步骤三:检查证书与 SNI
# 使用 openssl 测试 TLS 握手
openssl s_client -connect your.server.com:443 -servername your.server.com
步骤四:查看客户端日志
# 客户端日志通常输出到 stderr 或指定文件
journalctl -u hysteria-client -f
# 或
tail -f /var/log/hysteria/client.log
常见原因:
- 端口被占用或未放行;
- 证书过期或 SNI 不匹配;
- 密码错误;
- 客户端与服务端版本不兼容。
5.3 速率异常排查
步骤一:确认带宽配置
检查客户端与服务端的 bandwidth 配置是否匹配,是否存在一侧填得过高或过低。
步骤二:测试真实带宽
# 使用 iperf3 测试裸链路带宽
iperf3 -c your.server.com -p 5201 -t 30 -P 4
如果裸链路带宽远低于配置带宽,说明配置过高,需要下调。
步骤三:观察 RTT 变化
# 持续 ping 服务端,观察 RTT 是否稳定
ping -i 0.2 your.server.com
如果 RTT 持续上升,说明链路出现队列积压,通常是配置带宽超过容量所致。
步骤四:抓包分析
# 在服务端抓取 UDP 包,分析丢包与重传
tcpdump -i eth0 -n udp port 443 -w hysteria.pcap
# 使用 Wireshark 打开,过滤 quic 协议
关注指标:
- 重传率:重传包占比过高说明链路丢包严重;
- ACK 延迟:ACK 延迟上升说明链路拥塞;
- 流数量:流数量异常可能说明多路复用配置不当。
5.4 连接抖动排查
步骤一:检查 QUIC 空闲超时
quic:
maxIdleTimeout: 30s
如果超时设置过短,弱网下容易断开,建议适当调大。
步骤二:检查 UDP 会话超时
udpIdleTimeout: 60s
UDP 转发场景下,超时过短会导致会话频繁重建。
步骤三:检查运营商 QoS
部分运营商会针对 UDP 大流量进行限速或干扰,表现为连接周期性抖动。可以通过更换端口、启用混淆或改用 TCP 模式验证。
步骤四:查看系统日志
dmesg | grep -i udp
journalctl -u hysteria-server -f
关注是否有 connection reset、timeout 等关键字。
5.5 排障决策表
| 现象 | 可能原因 | 排查命令 | 修复措施 |
|---|---|---|---|
| 握手超时 | 端口未放行 | ss -ulnp | 放行端口 |
| 握手失败 | 证书/SNI 错误 | openssl s_client | 更换证书 |
| 速度低 | 带宽配置过高 | iperf3 | 下调配置 |
| RTT 上升 | 链路积压 | ping | 下调带宽 |
| 频繁断连 | 超时过短 | 查看日志 | 调大超时 |
| 上传慢 | 客户端 up 过高 | 测速 | 下调 up |
| 下载慢 | 服务端 up 过高 | 测速 | 下调 up |
5.6 客户端配置参考
如果你使用 Clash 或类似客户端,可以参考 客户端配置 专题中的 Hysteria2 配置模板,那里有更完整的 YAML 示例与参数说明。
小结
Hysteria2 的 Brutal 算法本质上是一次“用配置换性能”的工程取舍。它放弃了 TCP 式的动态探测,转而信任用户对链路容量的判断,以固定速率发送、以重传补偿丢包,从而在高丢包、高 RTT 链路上获得远超 CUBIC 与 BBR 的吞吐。代价是带宽参数必须填准,填高会引发链路拥塞,填低会浪费容量。对于自建专线、固定带宽 VPS、跨境加速等场景,Brutal 是目前最实用的用户态拥塞控制方案之一;而对于链路容量未知或剧烈波动的场景,传统 BBR 可能更稳妥。理解其机制、正确配置带宽、掌握排障方法,才能真正发挥 Hysteria2 的性能优势。
常见问题
Hysteria2 的 Brutal 算法和 BBR 有什么本质区别?
BBR 通过测量瓶颈带宽和最小 RTT 动态估算发送速率,仍属于反馈驱动;Brutal 则直接采用用户配置的固定速率发送,不依赖丢包反馈。因此在丢包严重的链路上 Brutal 更激进、吞吐更高,但配置带宽超过实际链路容量时会加剧拥塞。
Hysteria2 带宽参数填错会有什么后果?
若填写值远高于实际链路带宽,Brutal 会持续高速发送导致队列积压、延迟飙升甚至丢包加剧;若填写值过低,则无法跑满链路,吞吐被限制在配置值以下。建议以实测上下行带宽的 80% 至 90% 作为配置值。
Hysteria2 在丢包率多高时仍能保持可用?
在 20% 至 30% 的随机丢包下,Brutal 仍可维持接近配置带宽的吞吐,明显优于 CUBIC 和 BBR。但若丢包由链路中断或严重拥塞引起,固定速率会放大问题,此时应降低带宽配置或改用自适应拥塞控制。