发现自己写的跳板程序,连接总是很慢。慢到没法接受了,远程主机连接都要 10 多秒,只有自己动手来解决。因为我一直是使用的 Net::SSH::Perl 。还是只能基于这个模块来修改。因为接口之类最完善,也最 Perl 化。
其实我个人非常喜欢 Net::SSH2,因为速度非常快,不过接口是在没法接受。
在处理连接慢之前,其实都查过网上所有的其它同学写的文章了,大家一致认为是 Math::BigInt、Math::BigInt::GMP 和 Math::BigInt::Pari 这几个模块没装的原因。然后我发现我都安装了,还使用 cpanm 来重装了一次。结果没有变化。只能自己来追原因了。
我使用 @CGI.NET 同学推荐的 NYTProf 来跟程序到底那个地方慢。然后打开 HTML 来看看。
我们看到,第一个地方花了 21 秒,就用在连接的上面,点开接着查看源代码,最后测试是下面这段代码有问题。
01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
|
sub
_create_socket {
my
$ssh
=
shift
;
my
$sock
= gensym;
my
(
$p
,
$end
,
$delta
) = (0,1,1);
# normally we use whatever port we can get
(
$p
,
$end
,
$delta
) = (1023,512,-1)
if
$ssh
->{config}->get(
'privileged'
);
# allow an explicit bind address
my
$addr
=
$ssh
->{config}->get(
'bind_address'
);
$addr
= inet_aton(
$addr
)
if
$addr
;
(
$p
,
$end
,
$delta
) = (10000,65535,1)
if
$addr
and not
$p
;
$addr
||= INADDR_ANY;
for
(;
$p
!=
$end
;
$p
+=
$delta
) {
socket
(
$sock
, AF_INET, SOCK_STREAM,
getprotobyname
(
'tcp'
) || 0) ||
croak
"Net::SSH: Can't create socket: $!"
;
last
if
not
$p
or
bind
(
$sock
, sockaddr_in(
$p
,
$addr
));
if
($! =~ /Address already in
use
/i) {
close
(
$sock
) or
warn
qq{Could not
close
socket
: $!\n};
next
;
}
croak
"Net::SSH: Can't bind socket to port $p: $!"
;
}
if
(
$p
) {
$ssh
->debug(
"Allocated local port $p."
);
$ssh
->{config}->set(
'localport'
,
$p
);
}
$sock
;
}
|
因为我是使用 root 用户,所以默认的这个时候加了一个 bind 来对客户端端口进行绑定。这个时候因为 root 用户,所以是绑定的 1024 端口以后。我单独给上面的代码拿出来测试时,发现在最简单的 socket 的连接上。只要 bind 的端口小于 1024 都会非常非常慢。原因未知,我也没法解决。
使用 strace 来跟的时候,发现也是停止在这个绑定以后的连接。只要加了 bind 连接就常常超时。
1
2
|
bind
(3, {sa_family=AF_INET, sin_port=htons(1023), sin_addr=inet_addr(
"0.0.0.0"
)}, 16) = 0
connect
(3, {sa_family=AF_INET, sin_port=htons(22), sin_addr=inet_addr(
"xxx.xxx.xxx.xxx"
)}, 16
|
以我对 TCP/IP 的理解,好象没法解决这个问题了,原因只能靠大家来解决了。
我只能让整个流程绑定的端口指向 1024 以上,这种变态的方式来解决。也就是默认在 new 这个 Net::SSH::Perl 的对象的时候,加上一个 privileged => 0,来让我绑定都是以 1024 以上来绑定端口自由分配。
在这个地方做做记录,如果有相同的同学也发现自己写的 Net::SSH::Perl 很慢,可以考虑一下是不是相同的问题。