修复Git SSH拉取速度慢的问题 | AI生成和翻译
以下是调查和修复的完整说明。
问题
通过 SSH (git@github.com:QwenLM/Qwen2.5-Coder.git) 拉取 Qwen2.5-Coder 仓库时,下载速度仅为 81 KiB/s,需要拉取 2976 个对象(约 30 MB)。
调查步骤
步骤 1:检查 git 远程和代理配置
git -C /Users/lzwjava/projects/Qwen2.5-Coder remote -v
# → git@github.com:QwenLM/Qwen2.5-Coder.git (SSH)
git config --global --list | grep -iE 'proxy|http'
# → http.proxy=127.0.0.1:7890
# → https.proxy=127.0.0.1:7890
git 配置了 HTTP 代理(7890),但远程仓库使用的是 SSH —— 因此 git 的 http.proxy 不适用。SSH 有自己独立的代理路径。
步骤 2:检查 SSH 配置
cat ~/.ssh/config
找到关键行:
Host !192.168.*.*
ProxyCommand ncat --proxy localhost:7891 --proxy-type socks5 %h %p
这意味着所有非本地 SSH 连接(包括 GitHub)都通过 ncat → SOCKS5 代理(localhost:7891)进行。这是 SSH 的数据路径,与 git 的 HTTP 代理无关。
步骤 3:检查代理端口上运行的程序
lsof -i :7890 -sTCP:LISTEN
lsof -i :7891 -sTCP:LISTEN
两个端口均由 mihomo-da(PID 86998)提供服务 —— 即 mihomo(Clash Meta),你的本地代理。端口 7890 = HTTP 代理,端口 7891 = SOCKS5 代理。两者均正常运行。
步骤 4:直接测试代理速度
curl -x socks5h://localhost:7891 -o /dev/null -w "speed: %{speed_download}\n" https://github.com
# → ~1 MB/s — 代理速度快
curl -x http://127.0.0.1:7890 -o /dev/null -w "speed: %{speed_download}\n" https://github.com
# → ~980 KB/s — 同样很快
结论: 代理本身并非瓶颈。对于 HTTPS 流量,HTTP 和 SOCKS5 两条路径都很快。
步骤 5:测试 SSH 认证速度
time ssh -T git@github.com
# → 3.6 秒,认证成功
SSH 握手正常。慢的是认证后的数据传输阶段,而非连接建立阶段。
步骤 6:定位瓶颈
链路是:git fetch → SSH → ncat → SOCKS5 代理(7891)→ mihomo → 互联网。
ncat(来自 nmap 7.98)是薄弱环节。它被设计为网络工具,而非高吞吐量的 SSH 隧道代理。对于小数据包(认证、握手)表现尚可,但对于持续的大数据传输(git packfile),它会引入显著的开销 —— 这就是 81 KiB/s 与 1 MB/s 差异的原因。
对比:HTTPS 走的是:git → libcurl → HTTP 代理(7890)→ mihomo → 互联网。链路中没有 ncat。libcurl 针对批量传输进行了优化。
步骤 7:测试 HTTPS 拉取
GIT_TRACE=1 git -C /Users/lzwjava/projects/Qwen2.5-Coder fetch --depth=1
# → 413 个对象,约 77 秒,成功完成
从追踪信息看时间戳:
14:01:45.303 index-pack started (receiving data)
14:03:02.436 index-pack done
约 77 秒传输 413 个对象。原始 SSH 拉取需要获取 2976 个对象 —— 以 81 KiB/s 的速度,需要 10 分钟以上。
已执行的操作
将所有 5 个 Qwen 仓库从 SSH 切换为 HTTPS:
Qwen2-Audio: git@github.com → https://github.com/QwenLM/Qwen2-Audio.git
Qwen2.5-Coder: git@github.com → https://github.com/QwenLM/Qwen2.5-Coder.git
Qwen2.5-Math: git@github.com → https://github.com/QwenLM/Qwen2.5-Math.git
Qwen2.5-VL: git@github.com → https://github.com/QwenLM/Qwen2.5-VL.git
Qwen3: 已经是 HTTPS(无需更改)
使用的命令:
git -C /path/to/repo remote set-url origin https://github.com/QwenLM/RepoName.git
认证会自动工作,因为已配置 git-credential-manager。
关键要点
- git 中的 SSH 代理 ≠ HTTP 代理。
http.proxy仅影响 HTTPS 远程仓库。SSH 远程仓库使用~/.ssh/config中的 ProxyCommand。 ncat在批量 SSH 隧道传输中速度慢。 适合小数据交换,但对大型 packfile 传输表现很差。如果未来需要通过代理使用 SSH,connect(通过brew install connect安装)或nc -X 5 -x localhost:7891是更快的替代方案。- 对于大型仓库(模型权重、数据集),当拥有快速 HTTP 代理时,优先选择 HTTPS。 libcurl 路径针对批量数据进行了优化;通过 SOCKS5 的 SSH 会增加开销。
- 需要记住的排查命令:
lsof -i :PORT -sTCP:LISTEN—— 查看哪个进程在监听端口curl -x socks5h://localhost:PORT -o /dev/null -w "%{speed_download}" URL—— 测试代理速度GIT_TRACE=1 git fetch—— 查看 git 具体在哪个环节耗时git config --global --list | grep proxy—— 检查代理配置