热门标签 | HotTags
当前位置:  开发笔记 > 运维 > 正文

40案例篇:网络请求延迟变大了,我该怎么办?

除DDoS会带来网络延迟增大外,也有其他原因导致的网络延迟,比如网络传输慢,导致延迟Linux内核协议栈报文处理慢,导致延迟应用程序数据处理慢,导致延迟等等网络延迟提到网络延迟






除 DDoS会带来网络延迟增大外,也有其他原因导致的网络延迟, 比如



  1. 网络传输慢,导致延迟

  2. Linux内核协议栈报文处理慢,导致延迟

  3. 应用程序数据处理慢,导致延迟等等


网络延迟

提到网络延迟时,可能轻松想起它的含义---网络数据传输所用的时间

不过要注意,这个时间可能是单向的,指从源地址发送到目的地址的单程时间

也可能是双向的,即从源地址发送到目的地址,然后又从目的地址发回响应,这个往返全程所用的时间

通常更常用的是双向的往返通信延迟,比如ping测试的结果,就是往返延时RTT(Round-Trip Time)

除了网络延迟外

另一个常用的指标是应用程序延迟,它是指,从应用程序接收到请求, 再到发回响应,全程所用的时间

通常,应用程序延迟也指的是往返延迟,是网络数据传输时间加上数据处理时间的和

在Linux网络基础篇中,可以用ping来测试网络延迟

ping基于ICMP协议,它通过计算ICMP回显响应报文与ICMP回显请求报文的时间差,来获得往返延时

这个过程并不需要特殊认证,常被很多网络攻击利用,比如端口扫描工具nmap、组包工具hping3等等

所以为了避免这些问题,很多网络服务会把ICMP禁止掉

这也就导致我们无法用ping ,来测试网络服务的可用性和往返延时

这时可以用traceroute或hping3的TCP和UDP模式,来获取网络延迟

比如以baidu.com为例,可以执行下面的hping3命令,测试当前机器到百度搜索服务器的网络延迟

# -c表示发送3次请求
# -S表示设置TCP SYN
# -p表示端口号为80
root@alnk:~# hping3 -c 3 -S -p 80 baidu.com
HPING baidu.com (eth0 220.181.38.251): S set, 40 headers + 0 data bytes
len=46 ip=220.181.38.251 ttl=48 id=60840 sport=80 flags=SA seq=0 win=8192 rtt=47.9 ms
len=46 ip=220.181.38.251 ttl=49 id=62209 sport=80 flags=SA seq=1 win=8192 rtt=47.8 ms
len=46 ip=220.181.38.251 ttl=49 id=27368 sport=80 flags=SA seq=2 win=8192 rtt=47.8 ms
--- baidu.com hping statistic ---
3 packets transmitted, 3 packets received, 0% packet loss
round-trip min/avg/max = 47.8/47.8/47.9 ms
##
从hping3的结果中可以看到,往返延迟RTT为47ms

当然用traceroute,也可以得到类似结果

# --tcp 表示使用TCP协议
# -p 表示端口号
# -n 表示不对结果中的IP地址执行反向域名解析
root@alnk:~# traceroute --tcp -p 80 -n baidu.com
traceroute to baidu.com (220.181.38.148), 30 hops max, 60 byte packets
1 * * *
2 * * *
3 * * *
4 * * *
5 * * *
6 * * *
7 * * *
8 * * *
9 * * *
10 * * *
11 * * *
12 183.60.190.109 5.303 ms * *
13 * * *
14 * * *
15 * * *
16 * * *
17 * * *
18 * * *
19 * * *
20 * * *
21 10.166.96.36 46.231 ms 220.181.38.148 42.693 ms *
##
traceroute会在路由的每一跳发送三个包,并在收到响应后,输出往返延时
如果无响应或者响应超时(默认5s),就会输出一个星号


网络延迟升高时的分析思路案例



  1. 案例准备

    Ubuntu 18.04
    机器配置:2CPU,4GB内存
    预先安装docker、hping3、tcpdump、curl、wrk、Wireshark 等工具

    image-20211230141826613



  2. 在终端一中,执行下面的命令,运行官方Nginx,它会在80端口监听

    root@alnk:~# docker run --network=host --name=good -itd nginx


  3. 继续在终端一中,执行下面的命令,运行案例应用,它会监听8080端口

    root@alnk:~# docker run --name nginx --network=host -itd feisky/nginx:latency


  4. 在终端二中执行curl命令,验证两个容器已经正常启动

    # 80正常
    [root@local_deploy_192-168-1-5 ~]# curl http://124.71.83.217







    Welcome to nginx!

    If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.

    For online documentation and support please refer to
    nginx.org.

    Commercial support is available at
    nginx.com.

    Thank you for using nginx.




    # 8080正常
    [root@local_deploy_192-168-1-5 ~]# curl http://124.71.83.217:8080







    Welcome to nginx!

    If you see this page, the nginx web server is successfully installed and
    working. Further configuration is required.

    For online documentation and support please refer to
    nginx.org.

    Commercial support is available at
    nginx.com.

    Thank you for using nginx.






  5. 在终端二,执行下面的命令,分别测试案例机器80端口和8080端口的延迟

    # 测试80端口延迟
    [root@local_deploy_192-168-1-5 ~]# hping3 -c 3 -S -p 80 124.71.83.217
    HPING 124.71.83.217 (eth0 124.71.83.217): S set, 40 headers + 0 data bytes
    len=46 ip=124.71.83.217 ttl=48 DF id=0 sport=80 flags=SA seq=0 win=64240 rtt=9.8 ms
    len=46 ip=124.71.83.217 ttl=48 DF id=0 sport=80 flags=SA seq=1 win=64240 rtt=8.5 ms
    len=46 ip=124.71.83.217 ttl=48 DF id=0 sport=80 flags=SA seq=2 win=64240 rtt=7.4 ms
    --- 124.71.83.217 hping statistic ---
    3 packets transmitted, 3 packets received, 0% packet loss
    round-trip min/avg/max = 7.4/8.6/9.8 ms
    # 测试8080端口延迟
    [root@local_deploy_192-168-1-5 ~]# hping3 -c 3 -S -p 8080 124.71.83.217
    HPING 124.71.83.217 (eth0 124.71.83.217): S set, 40 headers + 0 data bytes
    len=46 ip=124.71.83.217 ttl=48 DF id=0 sport=8080 flags=SA seq=0 win=64240 rtt=8.5 ms
    len=46 ip=124.71.83.217 ttl=48 DF id=0 sport=8080 flags=SA seq=1 win=64240 rtt=7.7 ms
    len=46 ip=124.71.83.217 ttl=48 DF id=0 sport=8080 flags=SA seq=2 win=64240 rtt=7.6 ms
    --- 124.71.83.217 hping statistic ---
    3 packets transmitted, 3 packets received, 0% packet loss
    round-trip min/avg/max = 7.6/7.9/8.5 ms
    ##
    # 从这个输出你可以看到,两个端口的延迟差不多,都是8ms
    # 不过,这只是单个请求的情况。换成并发请求的话,又会怎么样呢?


  6. 在终端二中,执行下面的新命令,分别测试案例机器并发100时80端口和8080端口的性能

    # 测试80端口性能
    [root@local_deploy_192-168-1-5 ~]# wrk --latency -c 100 -t 2 --timeout 2 http://124.71.83.217/
    Running 10s test @ http://124.71.83.217/
    2 threads and 100 connections
    Thread Stats Avg Stdev Max +/- Stdev
    Latency 193.99ms 346.67ms 1.86s 87.16%
    Req/Sec 331.23 1.05k 6.59k 94.97%
    Latency Distribution
    50% 8.35ms
    75% 279.98ms
    90% 654.18ms
    99% 1.61s
    6564 requests in 10.01s, 5.34MB read
    Socket errors: connect 0, read 0, write 0, timeout 83
    Requests/sec: 655.87
    Transfer/sec: 546.72KB
    # 测试8080端口性能
    [root@local_deploy_192-168-1-5 ~]# wrk --latency -c 100 -t 2 --timeout 2 http://124.71.83.217:8080/
    Running 10s test @ http://124.71.83.217:8080/
    2 threads and 100 connections
    Thread Stats Avg Stdev Max +/- Stdev
    Latency 311.29ms 398.66ms 1.94s 83.58%
    Req/Sec 179.02 147.02 1.00k 93.50%
    Latency Distribution
    50% 57.17ms
    75% 463.84ms
    90% 827.38ms
    99% 1.69s
    3569 requests in 10.01s, 2.91MB read
    Socket errors: connect 0, read 0, write 0, timeout 31
    Requests/sec: 356.63
    Transfer/sec: 297.52KB
    ##
    # 从上面两个输出可以看到,官方Nginx(监听在80端口)的平均延迟是193.99ms|
    # 而案例Nginx的平均延迟(监听在8080端口)则是311.29ms
    ##
    结合上面hping3的输出很容易发现,案例Nginx在并发请求下的延迟增大了很多,这是怎么回事呢?


  7. 使用tcpdump抓取收发的网络包,分析网络的收发过程有没有问题

    在终端一中,执行下面的tcpdump命令,抓取8080端口上收发的网络 包,并保存到nginx.pcap文件

    root@alnk:~# tcpdump -nn tcp port 8080 -w nginx.pcap


  8. 终端二中,重新执行wrk命令

    [root@local_deploy_192-168-1-5 ~]# wrk --latency -c 100 -t 2 --timeout 2 http://124.71.83.217:8080/


  9. 当wrk命令结束后,再次切换回终端一,并按下Ctrl+C结束tcpdump命令

    然后,再把抓取到的nginx.pcap ,复制到装有Wireshark的机器中,并用Wireshark打开它

    由于网络包的数量比较多,可以先过滤一下

    比如,在选择一个包后,可以单击右键并选择 “Follow” -> “TCP Stream”,如下图所示

    image-20211230143522266

    然后,关闭弹出来的对话框,回到Wireshark主窗口,

    这时候会发现Wireshark已经自动帮你设置了一个过滤表达式 tcp.stream eq 24

    image-20211230143632878

    从这里可以看到这个TCP连接从三次握手开始的每个请求和响应情况,当然这可能还不够直观

    可以继续点击菜单栏里的Statics -> Flow Graph

    选中 “Limit to display filter” 并设置Flow type 为 “TCP Flows”

    image-20211230144235144

    注意这个图的左边是客户端,而右边是Nginx服务器

    通过这个图就可以看出,前面三次握手,以及第一次HTTP请求和响应还是挺快的

    但第二次HTTP请求就比较慢了,特别是客户端在收到服务器第一个分组后,40ms后才发出了ACK响应

    看到40ms这个值有没有想起什么东西呢?实际上,这是TCP延迟确认(Delayed ACK)的最小超时时间

    这是针对 TCP ACK 的一种优化机制,也就是说,不用每次请求都发送一个ACK

    而是先等一会儿(比如40ms),看看有没有“顺风车”

    如果这段时间内,正好有其他包需要发送,那就捎带着ACK一起发送过去

    当然,如果一直等不到其他包,那就超时后单独发送ACK

    因为案例中40ms发生在客户端,有理由怀疑,是客户端开启了延迟确认机制

    而这儿的客户端,实际上就是前面运行的wrk

    查询TCP文档(执行 man tcp)发现,只有TCP套接字专门设置了TCP_QUICKACK ,才会开启快速确认模式

    否则,默认情况下,采用的就是延迟确认机制

    为了验证猜想,确认wrk的行为,可以用strace ,来观察wrk为套接字设置了哪些TCP选项



  10. 终端二中,执行下面的命令

    [root@local_deploy_192-168-1-5 ~]# strace -f wrk --latency -c 100 -t 2 --timeout 2 http://124.71.83.217:8080/
    [pid 32138] setsockopt(5, SOL_TCP, TCP_NODELAY, [1], 4) = 0

    这样可以看到,wrk只设置了TCP_NODELAY选项,而没有设置TCP_QUICKACK

    这说明wrk采用的正是延迟确认,也就解释了上面这个40ms的问题

    不过别忘了,这只是客户端的行为,按理来说Nginx服务器不应该受到这个行为的影响

    那是不是分析网络包时漏掉了什么线索呢?回到Wireshark重新观察一 下

    image-20211230145545211

    仔细观察 Wireshark 的界面,其中, 1173号包,就是刚才说到的延迟ACK包

    下一行的1175 ,则是Nginx发送的第二个分组包

    它跟697号包组合起来,构成一个完整的HTTP响应(ACK号都是85)

    第二个分组没跟前一个分组697号一起发送,而是等到客户端对第一个分组的ACK后1173号才发送

    这看起来跟延迟确认有点像,只不过,这儿不再是ACK,而是发送数据

    看到这里想起了一个东西—— Nagle 算法(纳格算法)

    进一步分析案例前, 先简单介绍一下这个算法

    Nagle算法,是TCP协议中用于减少小包发送数量的一种优化算法,目的是为了提高实际带宽的利用率

    举个例子,当有效负载只有1字节时,再加上TCP头部和IP头部分别占用的20字节,整个网络包就是41字节

    这样实际带宽的利用率只有 2.4%(1/41)

    往大了说,如果整个网络带宽都被这种小包占满,那整个网络的有效利用率就太低了

    Nagle算法正是为了解决这个问题

    它通过合并TCP小包,提高网络带宽的利用率

    Nagle算法规定,一个TCP连接上,最多只能有一个未被确认的未完成分组

    在收到这个分组的ACK前,不发送其他分组

    这些小分组会被组合起来,并在收到ACK后,用同一个分组发送出去

    显然Nagle算法本身的想法还是挺好的,但是知道Linux默认的延迟确认机制后

    应该就不这么想了,因为它们一起使用时,网络延迟会明显。如下图所示

    image-20211230145956783

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

    同时由于Server端开启了Nagle,而这时还没收到第一个分组的ACK,Server也会 在这里一直等着

    直到40ms超时后,Client才会回复ACK,然后Server才会继续发送第二个分组

    既然可能是Nagle的问题,那该怎么知道,案例Nginx有没有开启Nagle呢?

    查询tcp的文档就会知道,只有设置了TCP_NODELAY后,Nagle算法才会禁用

    所以只需要查看Nginx的tcp_nodelay选项就可以了



  11. 终端一中,执行下面的命令,查看案例Nginx的配置

    root@alnk:~# docker exec nginx cat /etc/nginx/nginx.conf | grep tcp_nodelay
    tcp_nodelay off;
    ##
    # 果然看到案例Nginx的tcp_nodelay是关闭的,将其设置为on ,应该就可以解决了
    ##
    # 改完后问题是否就解决了呢?自然需要验证一下
    # 修改后的应用已经打包到了Docker镜像中,在终端一中执行下面的命令,就可以启动它
    # 删除案例应用
    root@alnk:~# docker rm -f nginx
    # 启动优化后的应用
    root@alnk:~# docker run --name nginx --network=host -itd feisky/nginx:nodelay


  12. 终端二,重新执行wrk测试延迟

    root@alnk:~# wrk --latency -c 100 -t 2 --timeout 2 http://124.71.83.217:8080/
    Running 10s test @ http://192.168.0.30:8080/
    2 threads and 100 connections
    Thread Stats Avg Stdev Max +/- Stdev
    Latency 9.58ms 14.98ms 350.08ms 97.91%
    Req/Sec 6.22k 282.13 6.93k 68.50%
    Latency Distribution
    50% 7.78ms
    75% 8.20ms
    90% 9.02ms
    99% 73.14ms
    123990 requests in 10.01s, 100.50MB read
    Requests/sec: 12384.04
    Transfer/sec: 10.04MB
    ##
    # 果然现在延迟已经缩短成了9ms,跟测试的官方Nginx镜像是一样的
    # Nginx默认就是开启tcp_nodelay的


  13. 终端一,停止案例

    root@alnk:~# docker rm -f nginx good




小结

今天学习了网络延迟增大后的分析方法

网络延迟是最核心的网络性能指标

由于网络传输、网络包处理等各种因素的影响,网络延迟不可避免

但过大的网络延迟,会直接影响用户的体验

所以在发现网络延迟增大后,可以用traceroute、hping3、tcpdump、Wireshark、 strace等多种工具

来定位网络中的潜在问题



  1. 使用hping3以及wrk等工具,确认单次请求和并发请求情况的网络延迟是否正常

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

  3. 使用tcpdump和Wireshark,确认网络包的收发是否正常

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

这样就可以依次从路由、网络包的收发、再到应用程序等,逐层排查,直到定位问题根源

转载请注明出处哟~

https://www.cnblogs.com/lichengguo


原文链接:https://www.cnblogs.com/lichengguo/p/15748912.html



推荐阅读
  • 本文比较了eBPF和WebAssembly作为云原生VM的特点和应用领域。eBPF作为运行在Linux内核中的轻量级代码执行沙箱,适用于网络或安全相关的任务;而WebAssembly作为图灵完备的语言,在商业应用中具有优势。同时,介绍了WebAssembly在Linux内核中运行的尝试以及基于LLVM的云原生WebAssembly编译器WasmEdge Runtime的案例,展示了WebAssembly作为原生应用程序的潜力。 ... [详细]
  • Nginx使用AWStats日志分析的步骤及注意事项
    本文介绍了在Centos7操作系统上使用Nginx和AWStats进行日志分析的步骤和注意事项。通过AWStats可以统计网站的访问量、IP地址、操作系统、浏览器等信息,并提供精确到每月、每日、每小时的数据。在部署AWStats之前需要确认服务器上已经安装了Perl环境,并进行DNS解析。 ... [详细]
  • 本文介绍了在rhel5.5操作系统下搭建网关+LAMP+postfix+dhcp的步骤和配置方法。通过配置dhcp自动分配ip、实现外网访问公司网站、内网收发邮件、内网上网以及SNAT转换等功能。详细介绍了安装dhcp和配置相关文件的步骤,并提供了相关的命令和配置示例。 ... [详细]
  • 近年来,大数据成为互联网世界的新宠儿,被列入阿里巴巴、谷歌等公司的战略规划中,也在政府报告中频繁提及。据《大数据人才报告》显示,目前全国大数据人才仅46万,未来3-5年将出现高达150万的人才缺口。根据领英报告,数据剖析人才供应指数最低,且跳槽速度最快。中国商业结合会数据剖析专业委员会统计显示,未来中国基础性数据剖析人才缺口将高达1400万。目前BAT企业中,60%以上的招聘职位都是针对大数据人才的。 ... [详细]
  • 本文介绍了数据库的存储结构及其重要性,强调了关系数据库范例中将逻辑存储与物理存储分开的必要性。通过逻辑结构和物理结构的分离,可以实现对物理存储的重新组织和数据库的迁移,而应用程序不会察觉到任何更改。文章还展示了Oracle数据库的逻辑结构和物理结构,并介绍了表空间的概念和作用。 ... [详细]
  • Linux重启网络命令实例及关机和重启示例教程
    本文介绍了Linux系统中重启网络命令的实例,以及使用不同方式关机和重启系统的示例教程。包括使用图形界面和控制台访问系统的方法,以及使用shutdown命令进行系统关机和重启的句法和用法。 ... [详细]
  • 本文主要讨论了在xps15上安装双系统win10和MacOS后,win10无法正常更新的问题。分析了可能的引导问题,并提供了解决方法。 ... [详细]
  • Centos7.6安装Gitlab教程及注意事项
    本文介绍了在Centos7.6系统下安装Gitlab的详细教程,并提供了一些注意事项。教程包括查看系统版本、安装必要的软件包、配置防火墙等步骤。同时,还强调了使用阿里云服务器时的特殊配置需求,以及建议至少4GB的可用RAM来运行GitLab。 ... [详细]
  • 本文介绍了在Hibernate配置lazy=false时无法加载数据的问题,通过采用OpenSessionInView模式和修改数据库服务器版本解决了该问题。详细描述了问题的出现和解决过程,包括运行环境和数据库的配置信息。 ... [详细]
  • 树莓派Linux基础(一):查看文件系统的命令行操作
    本文介绍了在树莓派上通过SSH服务使用命令行查看文件系统的操作,包括cd命令用于变更目录、pwd命令用于显示当前目录位置、ls命令用于显示文件和目录列表。详细讲解了这些命令的使用方法和注意事项。 ... [详细]
  • Metasploit攻击渗透实践
    本文介绍了Metasploit攻击渗透实践的内容和要求,包括主动攻击、针对浏览器和客户端的攻击,以及成功应用辅助模块的实践过程。其中涉及使用Hydra在不知道密码的情况下攻击metsploit2靶机获取密码,以及攻击浏览器中的tomcat服务的具体步骤。同时还讲解了爆破密码的方法和设置攻击目标主机的相关参数。 ... [详细]
  • Python语法上的区别及注意事项
    本文介绍了Python2x和Python3x在语法上的区别,包括print语句的变化、除法运算结果的不同、raw_input函数的替代、class写法的变化等。同时还介绍了Python脚本的解释程序的指定方法,以及在不同版本的Python中如何执行脚本。对于想要学习Python的人来说,本文提供了一些注意事项和技巧。 ... [详细]
  • 本文介绍了Oracle数据库中tnsnames.ora文件的作用和配置方法。tnsnames.ora文件在数据库启动过程中会被读取,用于解析LOCAL_LISTENER,并且与侦听无关。文章还提供了配置LOCAL_LISTENER和1522端口的示例,并展示了listener.ora文件的内容。 ... [详细]
  • 本文详细介绍了Linux中进程控制块PCBtask_struct结构体的结构和作用,包括进程状态、进程号、待处理信号、进程地址空间、调度标志、锁深度、基本时间片、调度策略以及内存管理信息等方面的内容。阅读本文可以更加深入地了解Linux进程管理的原理和机制。 ... [详细]
  • 图解redis的持久化存储机制RDB和AOF的原理和优缺点
    本文通过图解的方式介绍了redis的持久化存储机制RDB和AOF的原理和优缺点。RDB是将redis内存中的数据保存为快照文件,恢复速度较快但不支持拉链式快照。AOF是将操作日志保存到磁盘,实时存储数据但恢复速度较慢。文章详细分析了两种机制的优缺点,帮助读者更好地理解redis的持久化存储策略。 ... [详细]
author-avatar
秋梯田那路77
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有