首先之前说了DDos导致的响应缓慢的问题,DDos因为分布式 难以追踪的特点,导致没有办法可以完全的防御DDos带来的问题,只能设法缓解DDos的影响

比如专业的流量清洗工具和网络防火墙,在网络入口处阻断恶意流量,就能缓解很大一部分

服务器中加上DPDK XDP等方法,增大服务器抗攻击能力,应用程序中利用多级缓存 WAF CDN等方法继续宁缓解

但是只要进入服务器中,那么还是会带来一定的性能损失

除了DDos的攻击,还有很多其他的原因导致网络延迟,比如

网络传输慢,导致延迟

Linux内核处理报文慢,导致延迟

应用程序慢,导致延迟

我们看下上面说的,除了DDos之外的问题

首先是网络延迟

网络延迟,往往是说的一个包的来回双向消耗的时间,即从源地址发到目标地址,然后从目标地址发回响应,往返的全程时间

常见的Ping测试,就是统计的双向延迟RTT Round-Trip Time

而应用程序的延迟,就是应用程序从发出请求到获得响应的全程,其中在数据处理之外,就包括了网络传输的延迟

而Ping使用的ICMP。常用于一些网络攻击之中,比如端口扫描工具 nmap,组包工具hping3就可以组织ICMP相关网络攻击

为了保证不能有ICMP的相关攻击,很多网路服务都会将ICMP禁止掉,导致我们没有办法用ping来测试网络服务的可用性和往返延迟

还是考虑使用TCP或者UDP来获取网络延迟

比如baidu.com为例,可以执行如下的hping3,测试到百度搜索的服务器延迟

# -c表示发送3次请求,-S表示设置TCP SYN,-p表示端口号为80

$ hping3 -c 3 -S -p 80 baidu.com

HPING baidu.com (eth0 123.125.115.110): S set, 40 headers + 0 data bytes

len=46 ip=123.125.115.110 ttl=51 id=47908 sport=80 flags=SA seq=0 win=8192 rtt=20.9 ms

len=46 ip=123.125.115.110 ttl=51 id=6788  sport=80 flags=SA seq=1 win=8192 rtt=20.9 ms

len=46 ip=123.125.115.110 ttl=51 id=37699 sport=80 flags=SA seq=2 win=8192 rtt=20.9 ms

baidu.com hping statistic —

3 packets transmitted, 3 packets received, 0% packet loss

round-trip min/avg/max = 20.9/20.9/20.9 ms

来回的RTT的延迟为20.9ms

类似的traceroute可以获得类似的结果

# –tcp表示使用TCP协议,-p表示端口号,-n表示不对结果中的IP地址执行反向域名解析

$ traceroute –tcp -p 80 -n baidu.com

traceroute to baidu.com (123.125.115.110), 30 hops max, 60 byte packets

1  * * *

2  * * *

3  * * *

4  * * *

5  * * *

6  * * *

7  * * *

8  * * *

9  * * *

10  * * *

11  * * *

12  * * *

13  * * *

14  123.125.115.110  20.684 ms *  20.798 ms

上面的输出中,traceroute会在路由的每一跳发送三个包,然后得响应后,输出来回延迟,如果无响应,则是一个星号

接下来,我们拿着一个案例,学习网络延迟升高的分析思路

这次使用wrk Wireshark hping3 tcpdump等工具进行讲解

对于Wireshark,如果Linux没有图形化界面,则可以使用Win端的安装

然后启动一个Nginx的docker容器

$ docker run –name nginx –network=host -itd feisky/nginx:latency

b99bd136dcfd907747d9c803fdc0255e578bad6d66f4e9c32b826d75b6812724

在终端二中执行curl,验证容器是否正常启动

接下来使用hping3,来测试延迟,

# 测试8080端口延迟

$ hping3 -c 3 -S -p 8080 192.168.0.30

HPING 192.168.0.30 (eth0 192.168.0.30): S set, 40 headers + 0 data bytes

len=44 ip=192.168.0.30 ttl=64 DF id=0 sport=8080 flags=SA seq=0 win=29200 rtt=7.7 ms

len=44 ip=192.168.0.30 ttl=64 DF id=0 sport=8080 flags=SA seq=1 win=29200 rtt=7.6 ms

len=44 ip=192.168.0.30 ttl=64 DF id=0 sport=8080 flags=SA seq=2 win=29200 rtt=7.3 ms

— 192.168.0.30 hping statistic —

3 packets transmitted, 3 packets received, 0% packet loss

round-trip min/avg/max = 7.3/7.6/7.7 ms

这种单线程的请求,是7ms的延迟

那么,换成并发请求呢?分别是80端口和8080端口的性能

# 测试8080端口性能

$ wrk –latency -c 100 -t 2 –timeout 2 http://192.168.0.30:8080/

Running 10s test @ http://192.168.0.30:8080/

2 threads and 100 connections

Thread Stats   Avg      Stdev     Max   +/- Stdev

Latency    43.60ms    6.41ms  56.58ms   97.06%

Req/Sec     1.15k   120.29     1.92k    88.50%

Latency Distribution

50%   44.02ms

75%   44.33ms

90%   47.62ms

99%   48.88ms

22853 requests in 10.01s, 18.55MB read

Requests/sec:   2283.31

Transfer/sec:      1.85MB

性能比=并不高,平均的延迟高达44ms

对于此,我们需要进行相关的性能测试

首先是利用tcpdump命令进行相关的抓包

tcpdump    -nn tcp port 8080 -w nginx.pcap

然后切换到终端二上,重新执行wrk命令

进行并发的执行wrk命令

wrk –latency -c 100 -t 2 –timeout 2 http://192.168.0.30:8080

将抓取到的nginx.pcap,复制到装有Wireshark的机器,并用Wireshark打开

之后从界面话的Wireshark进行分析

图片

上图上可以了解,第二次的请求比第一次的请求间隔,大于了40ms,每次请求间隔要40ms,这跟TCP延迟确认的最小超时时间是一致的

这是不是开启了延迟确认的机制呢?

就是针对TCP ACK的优化机制,每次确认不会都发送一个ACK,而是多个ACK一起发回,如果一直等不到可以一起发送的ACK,则在一定时间后进行单独发送

对于这个延迟确认的机制是否开启?我们可以查看TCP套接字是不是设置了TCP_QUICKACK

如果设置了,就是开启快速确认机制,不然就是延迟确认机制

对于此套接字的确认,可以利用strace,来观察wrk为套接字设置了哪些TCP选项

strace -f wrk –latency -c 100 -t 2 –timeout 2 http://192.168.0.30:8080

在设置之中,wrk设置的套接字如下

$ strace -f wrk –latency -c 100 -t 2 –timeout 2 http://192.168.0.30:8080/

这样,wrk只设置了TCP_NODELAY的选项,导致了延迟确认

但是这样为何影响到了Nginx服务器呢?

根据Wireshark 的响应,我们查看如下的一点蛛丝马迹

图片

上面的1173包,是第一个请求的响应,但是第一个请求的响应,是跟着第二个分组包,1175,一起进行的ACK

这好比是TCP的Nagle算法

为了减少小包发送数量的一种优化算法

Nagle为了解决,每个数据包,无论数据多小,都有着TCP头和IP头占用的20个字节,如果全是小包,那么利用率就太低了

于是,为了解决这个问题,就通过合并TCP小包,提高利用率

但是当Nagle和延迟ACK一起使用的话,就会出现如下的场景

图片

Server发送第一个分组之后,由于Client开启了延迟确认,需要等待40ms才会回复ACK

Server端也开启了Nagle,导致Server因为没有第一个分组的ACK,也会一直等待

直到40ms超时之后,Client才会回复ACK,Server才会才会进行发送第二个分组

那么,接下来就是查看Nginx有没有开启Nagle了

Nginx也有对应的TCP_nodelay选项

查看Nginx的配置,

$ docker exec nginx cat /etc/nginx/nginx.conf | grep tcp_nodelay

tcp_nodelay    off;

发现tcp_nodealy是关闭的,设置为on即可解决

如上,便是今天的网络传输的优化解决方案

今天我们说了,发现网络延迟加大之后,可以使用traceroute hping3 tcpdump Wireshark strace等工具进行发现网络问题

使用hping3和wrk,查看网络延迟是否正常

使用traceroute 确认路由是否正确,查看路由中的每一跳网关延迟

使用tcpdump和Wireshark,确认网络包的收发

使用strace,观察应用程序对网络套接字的调用是否正常

依次,从路由,网络包的收发,应用程序等,进行逐层排查

发表评论

邮箱地址不会被公开。 必填项已用*标注