The TL;DR版本
看这个ASCII的演员阵容或这段视频 --然后想出发生这种情况的任何原因。下面的文本描述提供了更多的上下文。
设置的Details
ssh是在其上产生的,它连接到一个运行着SBC的SBC( Orange )。
使用the 3 Benchmarking链接
当使用iperf3进行基准测试时,膝上型计算机和SBC之间的连接比理论上的56 MBits/秒要小--正如预期的那样,因为这是一个非常“拥挤的2.4GHz”(公寓楼)内的WiFi连接。
更具体地说:在SBC上运行iperf3 -s之后,将在笔记本上执行以下命令:
# iperf3 -c 192.168.1.150
Connecting to host 192.168.1.150, port 5201
[ 5] local 192.168.1.89 port 57954 connected to 192.168.1.150 port 5201
[ ID] Interval Transfer Bitrate Retr Cwnd
[ 5] 0.00-1.00 sec 2.99 MBytes 25.1 Mbits/sec 0 112 KBytes
...
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 28.0 MBytes 23.5 Mbits/sec 5 sender
[ 5] 0.00-10.00 sec 27.8 MBytes 23.4 Mbits/sec receiver
iperf Done.
# iperf3 -c 192.168.1.150 -R
Connecting to host 192.168.1.150, port 5201
Reverse mode, remote host 192.168.1.150 is sending
[ 5] local 192.168.1.89 port 57960 connected to 192.168.1.150 port 5201
[ ID] Interval Transfer Bitrate
[ 5] 0.00-1.00 sec 3.43 MBytes 28.7 Mbits/sec
...
- - - - - - - - - - - - - - - - - - - - - - - - -
[ ID] Interval Transfer Bitrate Retr
[ 5] 0.00-10.00 sec 39.2 MBytes 32.9 Mbits/sec 375 sender
[ 5] 0.00-10.00 sec 37.7 MBytes 31.6 Mbits/sec receiver因此,基本上,上传到SBC大约是24 it /秒,从它(-R)下载达到32 it/秒。
带有SSH的Benchmarking
既然如此,让我们看看SSH的运行情况。在使用rsync和borgbackup时,我第一次遇到了导致这篇文章的问题-它们都使用SSH作为传输层.因此,让我们看看SSH如何在相同的链接上执行:
# cat /dev/urandom | \
pv -ptebar | \
ssh root@192.168.1.150 'cat >/dev/null'
20.3MiB 0:00:52 [ 315KiB/s] [ 394KiB/s]好吧,那是一个可怕的速度!比预期的链路速度慢得多.(如果您不知道pv -ptevar__:它显示当前和平均通过它的数据率)。在本例中,我们看到从/dev/urandom读取数据并通过SSH将数据发送到SBC平均达到400 SBC/S,即3.2MBits/秒,比预期的24 24MBits/秒要小得多。
为何我们的链路以其容量的13%运行?
也许是我们的/dev/urandom's的错吗?
# cat /dev/urandom | pv -ptebar > /dev/null
834MiB 0:00:04 [ 216MiB/s] [ 208MiB/s]不,绝对不是。
也许是SBC本身吗?也许这太慢了?让我们尝试运行相同的SSH命令(即向SBC发送数据),但这一次从通过以太网连接的另一台计算机(Machine 2)运行:
# cat /dev/urandom | \
pv -ptebar | \
ssh root@192.168.1.150 'cat >/dev/null'
240MiB 0:00:31 [10.7MiB/s] [7.69MiB/s] 不,这很好-- SBC上的SSH守护进程可以(很容易)处理它的以太网链路提供的11 11MBytes/秒(即100‘s/秒)。
在执行此操作时,是否加载了SBC的CPU?

不是的。
所以..。
iperf3),我们应该能够达到10倍的速度。到底是怎么回事?
<#>Netcat和ProxyCommand到救援
让我们试试普通的旧netcat连接--它们的运行速度是否与我们预期的一样快?
在巴塞尔公约中:
# nc -l -p 9988 | pv -ptebar > /dev/null在笔记本电脑里:
# cat /dev/urandom | pv -ptebar | nc 192.168.1.150 9988
117MiB 0:00:33 [3.82MiB/s] [3.57MiB/s] 它起作用了!并以预期的速度运行--更好,更快10倍--速度。
那么,如果我使用ProxyCommand运行SSH来使用nc,会发生什么呢?
# cat /dev/urandom | \
pv -ptebar | \
ssh -o "Proxycommand nc %h %p" root@192.168.1.150 'cat >/dev/null'
101MiB 0:00:30 [3.38MiB/s] [3.33MiB/s]工作!10倍的速度。
现在,我有点困惑--当使用“裸”nc作为Proxycommand时,您不是在做与SSH完全相同的事情吗?例如,创建一个套接字,连接到SBC的端口22,然后在它上铲SSH协议?
为什么产生的速度有这么大的差别?
这不是一个学术练习-我的borg备份运行速度比这快10倍。我只是不知道为什么:-)
编辑:添加了进程这里的“视频”。计算从ifconfig输出发送的数据包,很明显,在这两个测试中,我们都发送了40 it的数据,在大约30K的数据包中传输--只是在不使用ProxyCommand的情况下要慢得多。
发布于 2018-04-01 21:09:13
非常感谢在评论中提出意见的人。我把它们都看过了:
带有the转储的Recording包和WireShark中内容的比较
# tcpdump -i wlan0 -w good.ssh & \
cat signature | ssh -o "ProxyCommand nc %h %p" \
root@192.168.1.150 'cat | md5sum' ; \
killall tcpdump
# tcpdump -i wlan0 -w bad.ssh & \
cat signature | ssh root@192.168.1.150 'cat | md5sum' ; \
killall tcpdump在记录的数据包中没有任何重要的区别。
用于流量整形的Checking
我不知道这件事--但是在看了"tc“手册之后,我能够证实这一点。
tc filter show什么也不回tc class show什么也不回tc qdisc show...returns这些:
qdisc noqueue 0: dev lo root refcnt 2
qdisc noqueue 0: dev docker0 root refcnt 2
qdisc fq_codel 0: dev wlan0 root refcnt 2 limit 10240p flows 1024 quantum 1514 target 5.0ms interval 100.0ms memory_limit 32Mb ecn ...which似乎没有区分"ssh“和"nc”--实际上,我甚至不确定流量整形是否可以在进程级别上操作(我希望它能在IP报头中的地址/端口/区分服务字段上工作)。
Debian Chroot,以避免Arch客户端中潜在的“聪明”
不,同样的结果。
Finally - Nagle
在发送者中执行一次.
pv data | strace -T -ttt -f ssh 192.168.1.150 'cat | md5sum' 2>bad.log...and查看传输数据的套接字到底发生了什么,在实际传输开始之前我注意到了这个“设置”:
1522665534.007805 getsockopt(3, SOL_TCP, TCP_NODELAY, [0], [4]) = 0 <0.000025>
1522665534.007899 setsockopt(3, SOL_TCP, TCP_NODELAY, [1], 4) = 0 <0.000021>这将设置SSH套接字以禁用Nagle的算法。您可以搜索并阅读有关它的所有内容--但它的意思是SSH将响应性置于带宽之上--它指示内核立即发送写在这个套接字上的任何内容,而不是“延迟”等待来自远程的确认。
简单地说,这意味着,在默认配置中,SSH不是一种传输数据的好方法--而不是当使用的链接比较慢时(许多WiFi链接就是这种情况)。如果我们在空中发送“大部分是头”的数据包,那么带宽就浪费了!
为了证明这确实是罪魁祸首,我使用LD_PRELOAD“丢弃”了这个特定的syscall:
$ cat force_nagle.c
#include
#include
#include
#include
#include
int (*osetsockopt) (int socket, int level, int option_name,
const void *option_value, socklen_t option_len) = NULL;
int setsockopt(int socket, int level, int option_name,
const void *option_value, socklen_t option_len)
{
int ret;
if (!osetsockopt) {
osetsockopt = dlsym(RTLD_NEXT, "setsockopt");
}
if (option_name == TCP_NODELAY) {
puts("No, Mr Nagle stays.");
return 0;
}
ret = osetsockopt(socket, level, option_name, option_value, option_len);
return ret;
}
$ gcc -fPIC -D_GNU_SOURCE -shared -o force_nagle.so force_nagle.c -ldl
$ pv /dev/shm/data | LD_PRELOAD=./force_nagle.so ssh root@192.168.1.150 'cat >/dev/null'
No, Mr Nagle stays.
No, Mr Nagle stays.
100MiB 0:00:29 [3.38MiB/s] [3.38MiB/s] [================================>] 100% 有-完美的速度(嗯,就像iperf3一样快)。
故事的Morale
永不放弃:-)
如果您确实使用了像rsync或borgbackup这样的工具在SSH上传输数据,并且您的链接很慢,请尝试阻止SSH禁用Nagle (如上面所示)-或者使用ProxyCommand切换SSH以通过nc连接。这可以在$HOME/..ssh/config中自动完成:
$ cat .ssh/config
...
Host orangepi
Hostname 192.168.1.150
User root
Port 22
# Compression no
# Cipher None
ProxyCommand nc %h %p
......so表示,今后在ssh/rsync/borgbackup中所有使用"orangepi“作为目标主机的用户都将使用nc进行连接(因此不要使用D21)。
https://unix.stackexchange.com/questions/434825
复制相似问题