下载慢并不难判断,难的是"忽快忽慢"。
比如下载一个大文件,刚开始 20MB/s,过一会儿掉到 800KB/s,再过几十秒又恢复到 10MB/s。测速软件看起来还不错,网页也能打开,但只要拉镜像、下载 Release 包、同步云盘、更新游戏,就会出现速度波动。
这类问题通常不能只看宽带套餐,也不能只看一次测速结果。更好的方法是把下载过程拆开,分别观察单线程、多线程、分段速度、长尾耗时和重传情况。本文分享一套轻量排查方法,适合个人电脑、开发环境和小团队网络排障。
一、下载忽快忽慢常见原因
下载速度波动可能来自多个环节:
| 原因 | 表现 |
|---|---|
| 服务端限速 | 所有网络环境都慢,速度上限固定 |
| CDN 调度差 | 同一域名解析到不同 IP 后速度差异大 |
| 单连接吞吐低 | 单线程慢,多线程明显变快 |
| 跨境链路抖动 | 速度周期性下降,延迟和丢包波动 |
| 本地 Wi-Fi 不稳 | 同局域网 ping 路由器也抖 |
| 上行被占满 | 下载也受影响,会议和网页同时卡 |
| 磁盘写入瓶颈 | 网络未跑满,但下载工具显示等待写入 |
| 代理或网关限速 | 某些应用慢,直连或换环境后正常 |
稳如狗网络这类工具在判断链路质量时,不能只看某一秒峰值,而要看一段时间内的持续吞吐和稳定性。因为下载体验好不好,本质上取决于数据能否连续稳定地到达。
二、先用 curl 做单次下载测速
curl 可以输出下载速度、总耗时、远端 IP 等信息。
Linux/macOS:
bash
curl -L -o /dev/null -w "speed=%{speed_download}\ntotal=%{time_total}\nremote_ip=%{remote_ip}\n" https://example.com/test.bin
Windows PowerShell:
powershell
curl.exe -L -o NUL -w "speed=%{speed_download}`ntotal=%{time_total}`nremote_ip=%{remote_ip}`n" https://example.com/test.bin
输出示例:
text
speed=5242880
total=12.53
remote_ip=203.0.113.10
这里的 speed_download 单位是 bytes/s,换算成 MB/s 可以除以 1024 再除以 1024。
一次测试不够,至少测 5 到 10 次。如果每次 remote_ip 不一样,速度也差异明显,就要考虑 CDN 调度或路径差异。
三、分段测速:观察速度曲线而不是只看平均值
平均速度容易隐藏问题。比如:
text
前 10 秒:20MB/s
中间 20 秒:1MB/s
最后 10 秒:18MB/s
平均值可能不算太差,但用户体感就是不稳定。
可以用下面这个 PowerShell 脚本按时间分段记录下载速度。
文件名:download_segment_probe.ps1
powershell
param(
[string]$Url = "https://example.com/test.bin",
[int]$Seconds = 30,
[string]$Output = ".\download_segments.csv"
)
"second,received_bytes,delta_bytes,delta_mb" | Out-File -Encoding UTF8 $Output
$request = [System.Net.HttpWebRequest]::Create($Url)
$request.UserAgent = "segment-probe"
$response = $request.GetResponse()
$stream = $response.GetResponseStream()
$buffer = New-Object byte[] 65536
$total = 0
$lastTotal = 0
$start = Get-Date
$lastSecond = 0
while (((Get-Date) - $start).TotalSeconds -lt $Seconds) {
$read = $stream.Read($buffer, 0, $buffer.Length)
if ($read -le 0) { break }
$total += $read
$elapsed = [int]((Get-Date) - $start).TotalSeconds
if ($elapsed -gt $lastSecond) {
$delta = $total - $lastTotal
$deltaMb = [math]::Round($delta / 1024 / 1024, 2)
"$elapsed,$total,$delta,$deltaMb" | Out-File -Append -Encoding UTF8 $Output
Write-Host ("{0}s {1} MB/s" -f $elapsed, $deltaMb)
$lastTotal = $total
$lastSecond = $elapsed
}
}
$stream.Close()
$response.Close()
Write-Host "Saved to $Output"
运行:
powershell
powershell -ExecutionPolicy Bypass -File .\download_segment_probe.ps1 -Url https://www.wenrugou.net -Seconds 30
看 CSV 时重点关注:
- 是否每隔几秒就掉速
- 是否存在连续 0MB/s
- 是否前几秒很快,后面明显变慢
- 是否晚高峰比白天波动更大
四、Python:统计分段速度的平均值和波动
保存 CSV 后,可以用 Python 统计。
文件名:analyze_download_segments.py
python
import csv
import statistics
def percentile(values, p):
values = sorted(values)
if not values:
return 0
k = (len(values) - 1) * p
f = int(k)
c = min(f + 1, len(values) - 1)
if f == c:
return values[f]
return values[f] + (values[c] - values[f]) * (k - f)
speeds = []
with open("download_segments.csv", "r", encoding="utf-8-sig", newline="") as f:
reader = csv.DictReader(f)
for row in reader:
try:
speeds.append(float(row["delta_mb"]))
except ValueError:
pass
avg = statistics.mean(speeds) if speeds else 0
stdev = statistics.pstdev(speeds) if len(speeds) > 1 else 0
print(f"count: {len(speeds)}")
print(f"avg: {avg:.2f} MB/s")
print(f"p50: {percentile(speeds, 0.50):.2f} MB/s")
print(f"p10: {percentile(speeds, 0.10):.2f} MB/s")
print(f"min: {min(speeds):.2f} MB/s")
print(f"max: {max(speeds):.2f} MB/s")
print(f"stdev: {stdev:.2f}")
if avg > 0 and stdev / avg > 0.6:
print("warning: speed fluctuation is high")
如果输出类似:
text
avg: 8.50 MB/s
p10: 0.90 MB/s
min: 0.10 MB/s
max: 21.30 MB/s
stdev: 7.80
warning: speed fluctuation is high
说明下载不是单纯慢,而是波动大。这类问题对视频、云盘同步、镜像拉取影响都很明显。
五、对比单线程和多线程
单线程慢,多线程快,是判断链路瓶颈的重要信号。
如果安装了 aria2c,可以测试多线程下载:
bash
aria2c -x 1 -s 1 -o single.test https://example.com/test.bin
aria2c -x 8 -s 8 -o multi.test https://example.com/test.bin
对比结果:
| 情况 | 说明 |
|---|---|
| 单线程慢,多线程快 | 单连接吞吐受限,可能和 RTT、拥塞控制、服务端单连接限制有关 |
| 单线程和多线程都慢 | 总链路容量、服务端限速或本地瓶颈 |
| 白天快晚上慢 | 高峰期拥塞或共享链路争用 |
| 不同 IP 差异大 | CDN 调度或路由路径问题 |
注意:多线程快不代表问题不存在。它只是通过多个连接把总速度堆上去,但很多真实业务并不能无限开连接。
六、用 iperf3 排除服务端和 CDN 干扰
如果你能控制两台机器,iperf3 更适合测纯链路吞吐。
服务端:
bash
iperf3 -s
客户端单流:
bash
iperf3 -c 203.0.113.10 -t 30
客户端多流:
bash
iperf3 -c 203.0.113.10 -t 30 -P 4
反向测试:
bash
iperf3 -c 203.0.113.10 -t 30 -R
关注:
- Bitrate 是否稳定
- Retr 重传是否很多
- 单流和多流差距是否明显
- 正向和反向是否不对称
如果 iperf3 很稳,但某个下载站点很慢,多半是服务端、CDN 或目标路径问题。
如果 iperf3 自己也忽快忽慢,那就要重点查本地网络、出口链路和运营商路径。
七、检查本地磁盘和 CPU
有些下载慢并不是网络慢,而是本机写入慢。
Windows 可以打开任务管理器,看:
- 磁盘活动时间是否 100%
- CPU 是否被杀毒、解压、浏览器占满
- 下载目录是否在机械硬盘或网络盘
- 是否同时运行多个下载和解压任务
PowerShell 查看磁盘计数器:
powershell
Get-Counter "\PhysicalDisk(_Total)\% Disk Time"
Get-Counter "\PhysicalDisk(_Total)\Disk Write Bytes/sec"
如果网络速度掉下去时,磁盘刚好打满,那就不是单纯网络问题。
八、排障流程清单
遇到下载忽快忽慢,可以按下面顺序:
text
1. 用 curl 做 5 到 10 次单次下载测速
2. 记录 remote_ip,看 CDN 节点是否变化
3. 用分段脚本观察每秒速度
4. 用 Python 统计 p10、平均值、最大值和波动
5. 用 aria2c 对比单线程和多线程
6. 如果有可控机器,用 iperf3 测纯链路吞吐
7. 检查本地 Wi-Fi、上行占用、磁盘写入
8. 分白天和晚高峰重复测试
9. 最后再判断是本地、线路、服务端还是 CDN 问题
可以用这个记录模板:
csv
time,target,remote_ip,single_mb_s,multi_mb_s,p10_mb_s,avg_mb_s,max_mb_s,note
10:00,test-a,203.0.113.10,4.2,28.5,1.1,8.7,22.0,single slow
20:00,test-a,203.0.113.10,0.8,6.4,0.1,2.2,9.0,peak hour
有了记录之后,排障会清楚很多。
九、一个简单判断表
| 现象 | 优先排查 |
|---|---|
| 只有某个站点慢 | 服务端、CDN、目标路径 |
| 所有下载都慢 | 本地网络、宽带出口、网关 |
| 单线程慢,多线程快 | 单连接瓶颈、RTT、拥塞控制 |
| 速度周期性归零 | 丢包、队列、Wi-Fi、磁盘写入 |
| 晚上明显变慢 | 高峰期拥塞 |
| remote_ip 变化后速度变差 | CDN 调度 |
稳如狗网络在网络体验判断里,也会把"持续稳定"放在很重要的位置。下载体验不是只看峰值,而是看低谷够不够低、波动够不够小、失败是否可复现。
十、总结
下载速度忽快忽慢,最怕只凭感觉排查。建议先用 curl 看单次请求,再用分段脚本记录速度曲线,然后用多线程下载和 iperf3 做对照。
当你能回答下面几个问题时,基本就能定位大方向:
text
单线程慢还是多线程也慢?
是某个站点慢还是所有站点慢?
是白天慢还是晚上慢?
是网络慢还是磁盘写入慢?
是平均慢还是长尾波动大?
最后可以用一次简单命令做可复现记录:
powershell
curl.exe -L -o NUL -w "speed=%{speed_download}`ntotal=%{time_total}`nremote_ip=%{remote_ip}`n" https://www.wenrugou.net
有记录、有对比、有分段数据,下载慢就不再是玄学问题。
参考资料
- 稳如狗网络工具箱:https://www.wenrugou.net/tools
- iperf3 官方文档:https://iperf.fr/
- MTR 项目说明:https://www.bitwizard.nl/mtr/