wireshark排查网络延迟问题

wireshark可以说是网络问题排查的神器,里面的功能非常多,也很实用,本篇文章就是为一次课程试验,使用wireshark排查典型的网络场景。

一 试验环境搭建

采用的主机是版本都是centos 8.5版本,ip分别为192.168.31.50和192.168.31.200

[root@localhost ~]# cat /etc/centos-release
CentOS Linux release 8.5.2111
[root@localhost ~]# ip addr show ens33
2: ens33:  mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:cc:ff:99 brd ff:ff:ff:ff:ff:ff
    inet 192.168.31.50/24 brd 192.168.31.255 scope global noprefixroute ens33
       valid_lft forever preferred_lft forever
    inet6 fe80::31bf:afff:c603:4fa6/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever

[root@MiWiFi-RA72-srv wrk-master]# ip addr show ens33
2: ens33:  mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 00:0c:29:ed:16:d1 brd ff:ff:ff:ff:ff:ff
    inet 192.168.31.200/24 brd 192.168.31.255 scope global dynamic noprefixroute ens33
       valid_lft 39956sec preferred_lft 39956sec
    inet6 fe80::20c:29ff:feed:16d1/64 scope link 
       valid_lft forever preferred_lft forever
[root@MiWiFi-RA72-srv wrk-master]#

试验环境采用docker搭建:

docker run --network=host --name=good -itd nginx
docker run --name nginx --network=host -itd feisky/nginx:latenc

验证下是否正常:

[root@localhost ~]#  curl http://192.168.31.50:8080
...

Welcome to nginx!

.... [root@localhost ~]#  curl http://192.168.31.50 ...

Welcome to nginx!

....

均可正常运行,

二 开始试验

2.1 hping3 延迟测试

用hping3 测试延迟,这个两个都差不多,说明-c指定发送的包个数,-S发送SYN报文,-p指定服务器端的端口,下面跟着的是IP。

[root@MiWiFi-RA72-srv ~]# hping3  -c 3 -S -p 80 192.168.31.50 
HPING 192.168.31.50 (ens33 192.168.31.50): S set, 40 headers + 0 data bytes
len=46 ip=192.168.31.50 ttl=64 DF id=0 sport=80 flags=SA seq=0 win=29200 rtt=1.8 ms
len=46 ip=192.168.31.50 ttl=64 DF id=0 sport=80 flags=SA seq=1 win=29200 rtt=1.3 ms
len=46 ip=192.168.31.50 ttl=64 DF id=0 sport=80 flags=SA seq=2 win=29200 rtt=2.7 ms

--- 192.168.31.50 hping statistic ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 1.3/1.9/2.7 ms
[root@MiWiFi-RA72-srv ~]# hping3  -c 3 -S -p 8080 192.168.31.50 
HPING 192.168.31.50 (ens33 192.168.31.50): S set, 40 headers + 0 data bytes
len=46 ip=192.168.31.50 ttl=64 DF id=0 sport=8080 flags=SA seq=0 win=29200 rtt=0.6 ms
len=46 ip=192.168.31.50 ttl=64 DF id=0 sport=8080 flags=SA seq=1 win=29200 rtt=1.2 ms
len=46 ip=192.168.31.50 ttl=64 DF id=0 sport=8080 flags=SA seq=2 win=29200 rtt=2.0 ms

--- 192.168.31.50 hping statistic ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 0.6/1.2/2.0 ms

看了下,两个nginx的端口延迟差不多,都在2ms左右。

2.2 wrk测试应用性能

wrk的测试选项如下:

#  --latency     打印延迟统计
# -c 100 保持100个连接
# -t 4 个线程
#--timeout 2     socket请求超时时间  
 [root@MiWiFi-RA72-srv wrk-master]# wrk --latency -c 100 -t 4 --timeout 2 http://192.168.31.50/

测试80端口和8080端口:

[root@MiWiFi-RA72-srv wrk-master]# wrk --latency -c 100 -t 4 --timeout 2 http://192.168.31.50:8080/
Running 10s test @ http://192.168.31.50:8080/
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency    41.64ms    6.15ms  83.39ms   96.82%
    Req/Sec   601.11     81.26     1.05k    80.00%
  Latency Distribution
     50%   42.08ms
     75%   42.69ms
     90%   43.51ms
     99%   48.09ms
  24007 requests in 10.04s, 19.48MB read
Requests/sec:   2391.46
Transfer/sec:      1.94MB
[root@MiWiFi-RA72-srv wrk-master]# 
[root@MiWiFi-RA72-srv wrk-master]# 
[root@MiWiFi-RA72-srv wrk-master]# 
[root@MiWiFi-RA72-srv wrk-master]# wrk --latency -c 100 -t 4 --timeout 2 http://192.168.31.50
Running 10s test @ http://192.168.31.50
  4 threads and 100 connections
  Thread Stats   Avg      Stdev     Max   +/- Stdev
    Latency     5.29ms    7.57ms 105.21ms   95.68%
    Req/Sec     5.81k     2.07k   10.87k    63.66%
  Latency Distribution
     50%    3.36ms
     75%    5.91ms
     90%    9.66ms
     99%   39.66ms
  232036 requests in 10.09s, 188.76MB read
Requests/sec:  23005.97
Transfer/sec:     18.71MB

两个端口的差距还是很大的,一个Request/sec为2391个,且90%的延迟在43ms,而第二个Request/sec为2万3千多,90%的延迟在9ms左右,下面就要排查下原因。

2.3 原因排查

同样抓包,然后用wireshark打开,我们用两种方式看:通过流量图查看第一种方式,通过过滤流,然后查看”统计“里面的”流量图“。

  1. 我们先在wireshark中的列表中,右键,选择”追踪流“ 查看TCP流视图 , 然后关闭弹出窗口,这个好处是再过滤框中,自动显示过滤刚才选中的流。wireshark排查网络延迟问题_第1张图片

078f4ffee5dde984ef428acf1e6ff1d3.png 自动过滤流
  1. 查看流量图wireshark排查网络延迟问题_第2张图片注意勾选 限制显示过滤器,选择TCP Flow和任何地址。通过前面的时间来看,连续性没多大问题,每个包之间时间差比较小。

再看延迟大的情况:wireshark排查网络延迟问题_第3张图片

虽然这种方式也可以看到有的延迟增大,但是还不够直观,可以采用第二种方式。

往返时间统计图

  1. 通过”统计“菜单进入到"TCP流图形” 选择“往返时间”wireshark排查网络延迟问题_第4张图片

wireshark排查网络延迟问题_第5张图片 正常的往返时间

可以很清楚的看到,延迟大的往返时间很多延迟40ms以上,而正常的延迟,大部分点都在10ms之内。

延迟确认再通过第一种方法,可以看到,延迟大的都是确认包,而这个40ms,是TCP延迟确认的最小超时时间。

延迟确认:TCP对确认的一种优化,因为如果单独发确认包,信息携带的比较少,所以不是每次收到请求立刻回复确认包,而是延迟等一会(40ms这里),然后看看是否有包需要发送,有需要发送包的情况下,直接将ACK带过去,如果没有需要发送的数据,再单独发送确认包,所以就有40ms的延迟了。

查看TCP帮助,TCP_QUICKACK ,只有TCP套接字设置了这个选项才会开启快速确认。

TCP_QUICKACK (since Linux 2.4.4)
              Enable  quickack  mode  if  set  or  disable quickack mode if cleared.  In quickack mode, acks are sent immediately, rather than delayed if
              needed in accordance to normal TCP operation.  This flag is not permanent, it only enables a switch to or from quickack  mode.   Subsequent
              operation  of  the  TCP  protocol  will  once again enter/leave quickack mode depending on internal protocol processing and factors such as
              delayed ack timeouts occurring and data transfer.  This option should not be used in code intended to be portable.

这个时间和系统时钟频率有关系,它是一个宏定义:

#define TCP_DELACK_MAX  ((unsigned)(HZ/5))
#define TCP_DELACK_MIN   ((unsigned)(HZ/25))

看下本机时钟频率:

[root@MiWiFi-RA72-srv wrk-master]# cat /boot/config-4.18.0-305.3.1.el8.x86_64 |grep 'CONFIG_HZ='
CONFIG_HZ=1000

那么,最大时间就是1000/5 =200(ms),最小延迟时间1000/25= 40(ms),关闭延迟确认:

setsockopt(sock_fd,IPPROTO_TCP,TCP_QUICKACK,(char*)&value,sizeof(int));

那么来确认下wrk是否开启了这个选项:

[root@MiWiFi-RA72-srv wrk-master]# strace -e trace=network -f  wrk --latency -c 100 -t 4 --timeout 2 http://192.168.31.50
....
strace: Process 21316 attached
strace: Process 21318 attached
strace: Process 21319 attached
Running 10s test @ http://192.168.31.50
  4 threads and 100 connections
strace: Process 21317 attached
[pid 21317] socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) = 8
[pid 21317] connect(8, {sa_family=AF_INET, sin_port=htons(80), sin_addr=inet_addr("192.168.31.50")}, 16) = -1 EINPROGRESS (Operation now in progress)
[pid 21317] setsockopt(8, SOL_TCP, TCP_NODELAY, [1], 4) = 0
....

采用strace 跟踪所有和网络有关的系统调用,可以看到setsockopt(8, SOL_TCP, TCP_NODELAY, [1], 4)没有设置TCP_QUICKACK 。

那么问题来了,同样的命令为什么另外一个端口不会问题那。这里面仔细看报文,会发现,延迟大的时候,发送的包也在等,这就涉及到Nagle 算法(纳格算法)。

Nagle算法

Nagle 算法也是一种减少TCP小包发送数据包的一种优化算法,算法策略:1.没有发送未确认报文时候,立刻发送;2. 如果存在未确认报文,需要等到【没有已发送未确认报文】或者【数据包长度达到MSS大小】,再发送数据。

借用网上一张图表示:wireshark排查网络延迟问题_第6张图片启用这个算法后,如果我们通过telnet慢速敲入HELLO,刚开始要发送H,虽然包很小,但是没有需要确认的包,可以立刻发送,但是发送完毕后,由于H的确认还没有来,所以还必须等待,直到H报文的ACK报文来的,报文也积累了ELL三个字符,下面类似。不采用这个算法,可以看到,只要窗口够大,可以直接发送多个字符。

这个算法默认是开启的,关闭,可以通过设置socket 的TCP_NODELAY 选项来关闭。

TCP_NODELAY

If  set, disable the Nagle algorithm.  This means that segments are always sent as soon as possible, even if there is only a small amount of data.  When not set, data is buffered until there is a sufficient amount to send out, thereby avoiding the frequent sending of small packets, which results in poor utilization of the network.   This option is overridden by TCP_CORK; however, setting this option forces an explicit flush of pending output, even if TCP_CORK is currently set.

我们测试的nginx 是关闭的TCP_NODEAY,如下:

[root@localhost ~]# docker exec nginx cat /etc/nginx/nginx.conf|grep tcp_nodelay
    tcp_nodelay    off;

两种算法结合两种算法本来没啥问题,结合在一起的时候,就有可能导致延迟过大的问题,借用网上一位老哥的图,比较清晰的说明这个情况了:wireshark排查网络延迟问题_第7张图片我们这次试验中,wrk开启了延迟确认,而有问题的Nginx的镜像开启了Nagle算法,所以导致延迟比较大,不过我们的延迟是40ms。

你可能感兴趣的:(列表,linux,java,wireshark,网络通信)