了解 UNIX? 网络布局会帮助您了解自己的网络及其运行方式。但是,当 UNIX 网络性能和传输文件或连接服务的速度突然下降时,究竟发生了什么?如何诊断网络问题并找到网络中出现问题的地方?本文介绍一些快速发现和识别性能问题的方法以及解决问题的步骤。
简介
网络的性能对于环境其余部分的性能和可靠性影响很大。如果应用程序和服务等待通过网络传输的数据,或者客户机无法连接它们或接收信息,就需要解决这些问题。
性能问题还会影响应用程序和环境的可靠性。性能问题可能由网络故障导致,在某些情况下性能问题甚至是网络故障的原因。要想了解和诊断网络问题,首先需要了解问题的性质;问题往往与延时或带宽相关。
在一般情况下,网络性能问题常常与底层硬件有关;无法突破网络环境的物理限制。所有性能问题还常常与某种协议或系统相关,比如 NFS 或 Web 访问。但是,可以在操作系统中诊断和识别问题,决定正确的纠正措施。
本文讨论识别性能问题涉及的几个步骤:
确定基线性能水平
判断发生问题的位置
获得统计数据
识别瓶颈
了解网络指标
要想了解和诊断性能问题,首先需要确定基线性能水平。首先介绍在判断基线性能时使用的两个重要概念:网络延时和网络带宽。
网络延时
网络延时是向目的地发送请求到目的地实际接收到数据包之间的时间间隔。作为网络性能指标,延时增加说明网络繁忙,这意味着要传输的数据包数量超过了传输能力,数据的发送者在传输或重新传输之前必须等待。
当网络的复杂性以及数据包要经过的主机或网关数量增加时,也会增加网络延时。点之间的线缆长度也会影响延时。对于长距离线路,传统的铜线总是比光纤连接慢。
网络延时与应用程序延时不同。网络延时只与通过网络传输数据包相关,而应用程序延时是指应用程序接收请求到它做出响应之间的时间间隔。
网络带宽
带宽表示在特定的一段时间内可以通过网络传输的数据包数量。带宽影响可以传输的数据量,它把向一个主机传输数据的速度限制为网络连接支持的最大速度,在使用多个并发连接时限制总传输速度。
从理论上说,网络带宽应该不会变,除非改变网络接口和硬件。影响网络带宽的主要因素是在给定时刻使用网络的主机数量。
例如,1GB 的以太网接口可以向另一个网络主机传输 1GB 数据,或向 10 个主机同时传输 100MB,或向 100 个主机同时传输 10MB。当然,实际上常常不需要稳定的带宽。在一段时间内会有来自大量主机的许多小请求,服务器的可用带宽看起来可以比客户机带宽的总和大得多。
获得统计数据
在判断网络中是否发生问题之前,需要先确定基线性能,然后据此做出假设。为此,必须通过检查各种网络参数(与网络应用程序环境相关的延时、性能和测试)判断性能,然后监视和对比性能随时间的变化。
应该在可控制的状况下执行基线网络测试。在理想情况下,应该在隔离(没有其他网络通信流)和有典型的网络通信流两种场景中执行测试,这会提供两个基线:
对于隔离监视,应该在网络上没有其他通信流的情况下,检查服务器与一个或多个客户机之间的性能。这意味着要么关闭其他服务,要么把服务器和客户机放在一个隔离的网络环境中,这个环境与标准网络环境完全隔离(但是完全相同)。
对于标准监视,应该把客户机和服务器连接到标准网络,网络上有正常的背景通信流,但是除了要测试的服务器之外,禁用所有与应用程序相关的通信流(比如电子邮件、文件服务、Web 服务)。
对于实际测试过程,可以使用许多标准工具和测试判断基线值。
测量延时
所有网络管理员都很熟悉 ping 工具,使用它作为检查网络设备的可用性和延时的基本工具。在大多数机器上都可以使用 ping,包括客户机和服务器,只要它们已经配置为对 ping 工具发送给设备的 ICMP 数据包做出响应。简单地说,ping 向设备发送一个 echo 数据包,期望设备把数据包的内容发送回来。
在这个过程中,ping 可以监视发送数据包和接收响应花费的时间,这是测量 echo 过程的响应时间的有效方法。按照最简单的形式,可以向一个主机发送 echo 请求并查明响应时间(见清单 1)。
清单 1. 使用 ping 判断延时
$ ping example
PING example.example.pri (192.168.0.2): 56 data bytes
64 bytes from 192.168.0.2: icmp_seq=0 ttl=64 time=0.169 ms
64 bytes from 192.168.0.2: icmp_seq=1 ttl=64 time=0.167 ms
^C
— example.example.pri ping statistics —
2 packets transmitted, 2 packets received, 0% packet loss
round-trip min/avg/max/stddev = 0.167/0.168/0.169/0.001 ms
需要使用 Control-C 停止 ping 过程。在 Solaris 和 AIX? 上,需要使用 -s 选项发送多个 echo 数据包并获得计时信息。为了获得基线数据,可以使用 -c 选项(在 Linux? 上)指定数量。在 Solaris/AIX 上,可以指定数据包大小(默认大小为 56 字节)和要发送的数据包数量,这样就不必手工终止 ping 过程。然后可以自动地获得计时信息(见清单 2)。
清单 2. 在 Solaris/AIX 上使用 ping 时指定数据包大小
$ ping -s example 56 10
PING example: 56 data bytes
64 bytes from example.example.pri (192.168.0.2): icmp_seq=0. time=0.143 ms
64 bytes from example.example.pri (192.168.0.2): icmp_seq=1. time=0.163 ms
64 bytes from example.example.pri (192.168.0.2): icmp_seq=2. time=0.146 ms
64 bytes from example.example.pri (192.168.0.2): icmp_seq=3. time=0.134 ms
64 bytes from example.example.pri (192.168.0.2): icmp_seq=4. time=0.151 ms
64 bytes from example.example.pri (192.168.0.2): icmp_seq=5. time=0.107 ms
64 bytes from example.example.pri (192.168.0.2): icmp_seq=6. time=0.142 ms
64 bytes from example.example.pri (192.168.0.2): icmp_seq=7. time=0.136 ms
64 bytes from example.example.pri (192.168.0.2): icmp_seq=8. time=0.143 ms
64 bytes from example.example.pri (192.168.0.2): icmp_seq=9. time=0.103 ms
—-example PING Statistics—-
10 packets transmitted, 10 packets received, 0% packet loss
round-trip (ms) min/avg/max/stddev = 0.103/0.137/0.163/0.019
清单 2 中的示例是在网络比较空闲的时候得到的结果。如果在测试期间检查的主机(或网络本身)比较忙,那么 ping 时间会显著增加。只使用 ping 不足以表明是否有问题,但是有时候 ping 可以快速地查明是否有问题需要进一步诊断。
对 ping 的支持可能会禁用,所以在使用 ping 检查主机是否可用之前应该确认能够访问此主机。
理想情况下,应该在一段时间内连续地跟踪特定主机之间的 ping 时间,这样就可以得到平均响应时间,然后识别要检查的位置。
使用 sprayd
sprayd 守护进程和相关联的 spray 工具向指定的主机发送一个大的数据包流,判断这些数据包中有多少得到了响应。它是一种测量网络性能的方法,不应该把它当作性能指标,因为它使用无连接的传输机制。根据定义,使用无连接传输机制发送的数据包并不保证能够到达目的地,在通信中允许丢失数据包。
使用 spray 可以查明网络上是否有很多通信流,因为如果无连接传输 (UDP) 丢失许多数据包,就说明网络(或主机)太忙了。
在 Solaris、AIX 和其他一些 UNIX 平台上可以使用 spray。可能需要启用 spray 守护进程(通常通过 inetd)。启动 sprayd 守护进程之后,可以运行 spray 并指定主机名(见清单 3)。
清单 3. 使用 spray
$ spray tiger
sending 1162 packets of length 86 to tiger …
101 packets (8.692%) dropped by tiger
70 packets/sec, 6078 bytes/sec
正如前面提到的,不应该把速度作为可靠的性能指标,但是丢失的数据包数量是有意义的。
使用简单的网络传输测试
判断网络带宽性能的最佳方法是,在与机器收发数据时检查实际的速度。可以使用许多不同的工具执行跨许多应用程序和协议的测试,但是最简单的方法往往是最有效的。
例如,为了判断在使用 NFS 通过网络传输文件时的网络带宽,可以对一个简单的文件传输过程进行计时。为此,使用 mkfile 创建一个大文件(例如使用 $ mkfile 2g 2gbfile 创建一个 2GB 的文件),然后通过网络把它传输给另一台机器并计算花费的时间(见清单 4)。
清单 4. 计算通过网络把文件传输给另一台机器花费的时间
$ time cp /nfs/mysql-live/transient/2gbfile .
real 3m45.648s
user 0m0.010s
sys 0m9.840s
应该多次运行测试,然后求出传输过程的平均时间,从而比较准确地了解性能水平。
可以使用清单 5 这样的 Perl 脚本自动地执行复制和计时。
清单 5. 使用 Perl 脚本自动地执行复制和计时
#!/usr/bin/perl
use Benchmark;
use File::Copy;
use Data::Dumper;
my $file = shift or die “Need a file to copy from\n”;
my $srcdir = shift or die “Need a source directory to copy from\n”;
my $count = shift || 10;
my $t = timeit($count,sub {copy(sprintf(“%s/%s”,$srcdir,$file),$file)});
printf(“Time is %.2fs\n”,($t->[0]/$count));
在执行脚本时,指定源文件的名称和源目录以及可选的复制次数。然后执行脚本并得到一个时间值(见清单 6)。
清单 6. 执行 Perl 脚本
$ ./timexfer.pl 2gbfile /nfs/mysql-live/transient 20
Time is 28.45s
可以使用这种方法得到基线数据,也可以在正常操作期间检查传输性能。
诊断问题
通常,只有在与网络相关的应用程序由于某种原因失败时,您才会去寻找网络问题。但是,一定要确认问题是与网络相关的,而不是其他地方的问题。
首先,应该尝试使用 ping 连接机器。如果此机器对 ping 请求没有响应,其他网络通信机制也无效,那么首先应该检查物理线缆,确保所有设备仍然连接在一起。
如果仍然可以连接此机器,但是 ping 时间增加了,就需要判断出问题的位置。ping 时间增加有时候与机器上的负载相关,但更常见的原因是网络出了问题。
从一台机器得到比较长的 ping 时间之后,应该从网络上(最好在另一台网络交换机上)的另一台机器运行 ping,查明问题是与特定的机器相关,还是与网络相关。
检查网络统计数据
如果 ping 时间高于预期,那么应该开始收集关于正在使用的网络接口的一些基本统计数据,查明问题是与这个网络接口相关,还是与某种协议相关。
在 Linux 上,可以使用 ifconfig 工具获取一些基本网络统计信息(见清单 7)。
清单 7. 使用 ifconfig 工具获取基本网络统计信息
$ ifconfig eth1
eth1 Link encap:Ethernet HWaddr 00:1a:ee:01:01:c0
inet addr:192.168.0.2 Bcast:192.168.3.255 Mask:255.255.252.0
inet6 addr: fe80::21a:eeff:fe01:1c0/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:7916836 errors:0 dropped:78489 overruns:0 frame:0
TX packets:6285476 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:11675092739 (10.8 GiB) TX bytes:581702020 (554.7 MiB)
Interrupt:16 Base address:0x2000
以 RX 和 TX 开头的行很重要,它们提供关于发送和接收的数据包的信息。packets 值是传输的数据包的数量。errors、dropped 和 overruns 值表示出现某种错误的数据包的数量。如果与发送的数据包相比丢失的数据包数量比较高,可能说明网络忙。
在所有平台上,还可以使用 netstat 工具获得更详细的统计信息。在 Linux 上,此工具提供与协议相关的统计数据,比如 TCP-IP 和 UDP 数据包的传输情况。其中也包含一些基本统计数据(见清单 8)。
清单 8. 使用 netstat
$ netstat -s
Ip:
8437387 total packets received
1 with invalid addresses
0 forwarded
0 incoming packets discarded
8437383 incoming packets delivered
6820934 requests sent out
6 reassemblies required
3 packets reassembled ok
Icmp:
502 ICMP messages received
3 input ICMP message failed.
ICMP input histogram:
destination unreachable: 410
echo requests: 82
echo replies: 10
1406 ICMP messages sent
0 ICMP messages failed
ICMP output histogram:
destination unreachable: 1313
echo request: 11
echo replies: 82
IcmpMsg:
InType0: 10
InType3: 410
InType8: 82
OutType0: 82
OutType3: 1313
OutType8: 11
Tcp:
8361 active connections openings
6846 passive connection openings
1 failed connection attempts
164 connection resets received
33 connections established
8305361 segments received
6688553 segments send out
640 segments retransmitted
0 bad segments received.
676 resets sent
Udp:
126083 packets received
1294 packets to unknown port received.
0 packet receive errors
130335 packets sent
UdpLite:
TcpExt:
5 packets pruned from receive queue because of socket buffer overrun
6792 TCP sockets finished time wait in fast timer
5681 delayed acks sent
Quick ack mode was activated 11637 times
150861 packets directly queued to recvmsg prequeue.
74333 bytes directly in process context from backlog
9141882 bytes directly received in process context from prequeue
3608274 packet headers predicted
42627 packets header predicted and directly queued to user
77132 acknowledgments not containing data payload received
374105 predicted acknowledgments
2 times recovered from packet loss by selective acknowledgements
77 congestion windows recovered without slow start after partial ack
1 TCP data loss events
17 timeouts after SACK recovery
2 fast retransmits
8 retransmits in slow start
236 other TCP timeouts
1453 packets collapsed in receive queue due to low socket buffer
11634 DSACKs sent for old packets
2 DSACKs sent for out of order packets
2 DSACKs received
77 connections reset due to unexpected data
50 connections aborted due to timeout
TCPDSACKIgnoredNoUndo: 1
TCPSackShiftFallback: 23
IpExt:
InBcastPkts: 4126
在 Solaris 和其他 UNIX 平台上,netstat 提供的信息因平台而异。例如,在 Solaris 上,会获得针对每个协议的详细统计数据,以及分别针对 IPv4 和 IPv6 连接的信息(见清单 9)。下面的清单给出一部分输出。
清单 9. 在 Solaris 上使用 netstat
$ netstat -s
RAWIP rawipInDatagrams = 440 rawipInErrors = 0
rawipInCksumErrs = 0 rawipOutDatagrams = 91
rawipOutErrors = 0
UDP udpInDatagrams = 15756 udpInErrors = 0
udpOutDatagrams = 16515 udpOutErrors = 0
TCP tcpRtoAlgorithm = 4 tcpRtoMin = 400
tcpRtoMax = 60000 tcpMaxConn = -1
tcpActiveOpens = 1735 tcpPassiveOpens = 54
tcpAttemptFails = 2 tcpEstabResets = 35
tcpCurrEstab = 2 tcpOutSegs =13771839
tcpOutDataSegs =13975728 tcpOutDataBytes =1648876686
tcpRetransSegs = 90215 tcpRetransBytes =130340273
tcpOutAck =151539 tcpOutAckDelayed = 5570
tcpOutUrg = 0 tcpOutWinUpdate = 31
tcpOutWinProbe = 86 tcpOutControl = 3750
tcpOutRsts = 63 tcpOutFastRetrans = 6
tcpInSegs =7548720
tcpInAckSegs =2882026 tcpInAckBytes =1648874900
tcpInDupAck =4413016 tcpInAckUnsent = 0
tcpInInorderSegs =415007 tcpInInorderBytes =367832646
tcpInUnorderSegs = 7650 tcpInUnorderBytes =10389516
tcpInDupSegs = 222 tcpInDupBytes = 74649
tcpInPartDupSegs = 0 tcpInPartDupBytes = 0
tcpInPastWinSegs = 0 tcpInPastWinBytes = 0
tcpInWinProbe = 0 tcpInWinUpdate = 2
tcpInClosed = 33 tcpRttNoUpdate = 660
tcpRttUpdate =2880379 tcpTimRetrans = 2262
tcpTimRetransDrop = 10 tcpTimKeepalive = 630
tcpTimKeepaliveProbe= 314 tcpTimKeepaliveDrop = 17
tcpListenDrop = 0 tcpListenDropQ0 = 0
tcpHalfOpenDrop = 0 tcpOutSackRetrans = 69348
…
在所有情况下,都要寻找比较高的错误数据包、重新传输或丢失数据包传输数量,这些都说明网络忙。如果与传输或接收的数据包相比错误率很高,可能说明网络硬件有问题。
检查 NFS 统计数据
在检查与 NFS 连接和大多数其他网络应用程序相关的问题时,首先应该确定这个问题与机器上的问题无关,比如高负载(这会显著影响处理请求的速度)。使用 uptime 和 ps 检查进程,就可以查明机器是否很忙。
还可以检查 NFS 服务生成的 NFS 统计数据。nfsstat 命令生成关于 NFS 服务的服务器端和客户端的详细统计数据。例如,通过使用 -s 命令行选项并用 -v 选项指定 NFS 版本,可以生成关于 NFS 服务的服务器端的 NFS v3 统计数据(见清单 10)。
清单 10. 带 -s 和 -v 命令行选项的 nfsstat 命令
$ nfsstat -s -v3
Server rpc:
Connection oriented:
calls badcalls nullrecv badlen xdrcall dupchecks dupreqs
36118 0 0 0 0 410 0
Connectionless:
calls badcalls nullrecv badlen xdrcall dupchecks dupreqs
75 0 0 0 0 0 0
Server NFSv3:
calls badcalls
35847 0
Version 3: (35942 calls)
null getattr setattr lookup access readlink
15 0% 190 0% 83 0% 3555 9% 21222 59% 0 0%
read write create mkdir symlink mknod
9895 27% 300 0% 7 0% 0 0% 0 0% 0 0%
remove rmdir rename link readdir readdirplus
0 0% 0 0% 0 0% 0 0% 37 0% 20 0%
fsstat fsinfo pathconf commit
521 1% 2 0% 1 0% 94 0%
Server nfs_acl:
Version 3: (0 calls)
null getacl setacl getxattrdir
0 0% 0 0% 0 0% 0 0%
badcalls 值高表示有无效的请求发送给服务器,这说明客户机由于软件问题或硬件故障工作不正常,正在提交无效的请求。
大型网络中的 ping 时间
如果可以 ping 通机器,但是网络性能仍然有问题,就需要判断网络中出现性能问题的位置。在大型网络中,路由器把整个网络分隔为多个网段,可以使用 traceroute 工具判断两台机器之间的路由中的某个点是否出了问题。
traceroute 工具与 ping 工具相关,它通常提供网络数据包传输所经过的每个路由器的 ping 时间。在大型网络中,这有助于缩小问题的位置范围。在 Internet 上使用许多路由器在不同的 Internet Service Providers (ISP) 之间传输数据包,在通过 Internet 发送数据包时,也可以使用 traceroute 识别潜在的问题。
例如,清单 11 显示英国的两个办公室(它们使用不同的 ISP)之间的 traceroute。在这里,由于故障无法连接目的地机器。
清单 11. 英国的两个办公室之间的 traceroute
$ traceroute gendarme.example.com
traceroute to gendarme.example.com (82.70.138.102), 30 hops max, 40 byte packets
1 voyager.example.pri (192.168.1.1) 14.998 ms 95.530 ms 4.922 ms
2 dsl.vispa.net.uk (83.217.160.18) 32.251 ms 95.674 ms 30.742 ms
3 rt-gw1.tcm.vispa.net.uk (62.24.228.1) 49.178 ms 47.718 ms 123.261 ms
4 195.50.119.249 (195.50.119.249) 47.036 ms 50.440 ms 143.123 ms
5 ae-11-11.car1.Manchesteruk1.Level3.net (4.69.133.97) 92.398 ms 137.382 ms
52.780 ms
6 PACKET-EXCH.car1.Manchester1.Level3.net (195.16.169.90) 45.791 ms 140.165 ms
35.312 ms
7 spinoza-ae2-0.hq.zen.net.uk (62.3.80.54) 33.034 ms 39.442 ms 33.253 ms
8 galileo-fe-3-1-172.hq.zen.net.uk (62.3.80.174) 34.341 ms 33.684 ms 33.703 ms
9 * * *
10 * * *
11 * * *
12 * * *
在小型网络中,很可能没有分隔网络的路由器,所以 traceroute 不会有任何帮助。ping 和 traceroute 都依靠连接主机来判断问题。
现在,您已经掌握了处理 UNIX 网络性能问题的基本知识和技术。
结束语
很难在一台机器上确定 UNIX 网络性能问题,因为问题可能出现在网络中的任何地方。但是,可以在网络中的多个位置使用 ping 和 traceroute 检查性能,从而缩小问题位置的范围。初步了解了问题之后,可以使用其他网络工具获得关于造成问题的协议或应用程序的详细信息。本文讨论了获得基线信息的基本方法,然后介绍了用来识别问题的一些工具。