花拾录
← 返回知识库

用 SFTP 传几个 GB 的大文件太慢:换协议比调参数有效得多

云计算 / 运维导入2026/09/220 阅读0 评论

你要把几个 GB 的镜像或数据包从一台机器搬到另一台。手边最顺手的工具当然是 SSH——两台机器已经配好了密钥,sftp 传文件天经地义。但传着传着你会发现速度慢得让人怀疑人生:明明内网是千兆,实际速率却只有十几 MB/s,甚至更低。

现象

  • 用 SSH 库的 SFTP 接口传大文件,速度长期在低位徘徊;
  • scp 也快不到哪里去(很多实现底层走的还是同一套机制);
  • 换 rsync 有改善,但同样达不到内网应有的水平;
  • 而对小文件,这个速度你完全感觉不到——所以这个问题往往要到"搬大数据"的时候才暴露。

根因

SFTP 慢不是配置错了,是协议本身的开销。

SFTP 是跑在 SSH 连接之上的一个子系统(subsystem),每一批数据都要经过 SSH 的加密与通道封装。它的数据交换是请求/应答式的:客户端发一批数据,等服务端确认,再发下一批。这个"发一批、等一次确认"的节奏,在高延迟或默认窗口较小时,会把带宽利用率压得很低——链路很快,但数据是一小口一小口喂过去的,慢在"来回打招呼"上,而不是慢在链路上。

简单说:SFTP 是为"安全可靠地传文件"设计的,不是为"跑满带宽"设计的。 它的每一轮都要等待确认,加上加密和封装开销,在内网这种"链路根本不是瓶颈"的环境里,开销就成了瓶颈。

解决

思路是:换一个开销更小的协议来搬数据,只在传输的控制环节保留 SSH。

最省事的方案是在源端起一个临时 HTTP 服务,目标端直接拉:

# 源端:在待传文件所在目录起一个临时 HTTP 服务(默认监听 8000)
cd /path/to/files
python -m http.server 8000

# 目标端:直接拉,用 curl 或 wget
curl -O http://<源端IP>:8000/bigfile.tar.gz

实测千兆内网里,这样能跑到 100 MB/s 出头(接近千兆链路的实际上限),数 GB 的文件几十秒就传完了,比 SFTP 快一个量级。

几个实践要点:

  • 只在你信任的网段里这么干,比如内网直连的两台机器。临时 HTTP 服务默认没有加密、没有鉴权,别直接暴露到不可信网络。
  • 传完记得把服务停掉、把端口关掉,别让它长期挂着(这类"临时起的服务忘了关"本身就是另一类常见事故)。
  • 源端防火墙要放行这个端口(内网机器上通常默认就是放行的,但心里要有数)。
  • 如果是双向、增量同步,用 rsync 更合适;单纯的一次性大文件搬运,HTTP 直拉最直接。
  • 传输大文件时顺手核对一下哈希(sha256sum 两端一致),别只看"命令跑完了"。

延伸与预防

这条坑的通用教训是:传输慢时,换协议往往比调参数有效得多。

这条经验不止适用于 SFTP 和 HTTP 的对比,它是一个更一般的排查原则:

  • 先分清"链路慢"还是"协议慢"。 同样是拖一个大文件,用浏览器直接下载很快、用某个工具就很慢,那八成是工具/协议的开销问题,而不是网络问题。反过来,如果所有方式都慢,才轮到怀疑链路本身。
  • 同类替换清单。 传文件可以在 SFTP / HTTP / rsync / 本地磁盘搬运之间换;抓网页可以在标准库 / 请求库 / 命令行工具之间换(这几条的对比见网络抓取那一部分的案例);拉镜像有专门的 registry 协议。遇到"某个通道就是慢",第一反应应该是"有没有开销更小的通道",而不是去调它的缓冲区参数。
  • 安全与速度要一起想。 HTTP 直拉快,是因为它省掉了加密和逐批确认——代价就是明文、无鉴权。用之前先确认这段链路是不是"本来就不需要加密"的内网,确保省下来的开销没把安全性一起省掉。
  • 小文件察觉不到、大文件才暴露。 很多事情在"样本很小"的时候都是正常的:小文件传得飞快、小表查得飞快、少量请求都很稳。所以评估一个方案时,要有意识地在"真实规模"上测一次,别拿玩具样本的结论去指导生产。

评论(0)

  • 还没有评论,来抢沙发~

相关文章