要点
基本概念
TCP状态转换
TCP的状态变迁图如下:
掌握TCP的状态变迁,对分析 络问题,有着非常重要的意义。结合tcpdump工具,能发现很多 络相关的问题。
连接建立与关闭
通过上图,可以清晰地知道,每个系统函数调用之后,TCP的状态转换过程,对于定位应用程序的 络相关问题,有重要帮助。
复位 文
TCP首部中的RST比特是用于“复位”的,一般情况是:到不存在的端口的连接请求和异常终止一个连接。
backlog
它表示未完成连接队列和已经完成连接队列之各。如果连接队列中已没有空间,对于新的连接请求,TCP将不会理会收到的SYN,也不发回RST。
SO_KEEPALIVE
TCP套接字设置该选项后,如果2小时内(tcp_keepalive_time)内,在该套接字的任一方向上都没有数据交换,TCP就自动给对端发送一个保活探测 文。这是一个对端必须响应的TCP分节,它会导致以下三种情况之一:
UDP
UDP是一种面向 文的、无连接、不可靠的通信协议,它支持一对一,一对多,多对一和多对多的通信方式。在能容忍数据包丢失,实时性要求较高的场景中,可以考虑使用,如视频、直播等。
分析工具
netstat
查看 络连接状态。
# netstat -napActive Internet connections (servers and established)Proto Recv-Q Send-Q Local Address Foreign Address State PID/Program nametcp 0 0 0.0.0.0:22 0.0.0.0:* LISTEN 1321/sshdtcp 0 0 10.17.0.11:43026 10.10.10.1:8086 ESTABLISHED 31714/agenttcp 0 0 10.17.0.11:58238 10.10.10.2:5574 ESTABLISHED 21114/Service
tcpdump
抓取数据包工具。
# tcpdump -i eth0
# tcpdump -i eth0 host 10.1.1.2
tcpdump -i eth0 host 10.1.1.2 and port 3344
tcpdump -i eth0 src host 10.1.1.2
tcpdump -i eth0 dst host 10.1.1.2
sar
查看 络相关的历史统计数据。
# sar -n DEV 1Linux 3.10.0-1127.19.1.el7.x86_64 (VM-0-11-centos) 2021年11月05日 _x86_64_ (1 CPU)18时14分14秒 IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s18时14分15秒 eth0 17.00 17.00 2.88 4.27 0.00 0.00 0.0018时14分15秒 lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00^C18时14分15秒 IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s18时14分16秒 eth0 18.52 14.81 1.48 2.56 0.00 0.00 0.0018时14分16秒 lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00平均时间: IFACE rxpck/s txpck/s rxkB/s txkB/s rxcmp/s txcmp/s rxmcst/s平均时间: eth0 17.53 16.23 2.39 3.67 0.00 0.00 0.00平均时间: lo 0.00 0.00 0.00 0.00 0.00 0.00 0.00
iftop
可以用来查看 卡的实时流量信息,中间的箭头表示流量方向。
traceroute
显示数据包到指定主机之间的路由信息,可以检查 络延时。
# traceroute github.comtraceroute to github.com (20.205.243.166), 30 hops max, 60 byte packets 1 9.30.191.130 (9.30.191.130) 2.445 ms 2.714 ms 2.959 ms 2 9.30.251.110 (9.30.251.110) 2.172 ms 2.391 ms 2.523 ms 3 10.196.36.126 (10.196.36.126) 2.234 ms 2.417 ms 10.196.36.62 (10.196.36.62) 2.215 ms 4 10.200.65.101 (10.200.65.101) 2.986 ms 10.200.65.121 (10.200.65.121) 3.352 ms 10.200.65.101 (10.200.65.101) 2.838 ms 5 10.162.5.110 (10.162.5.110) 3.908 ms 101.227.217.26 (101.227.217.26) 2.977 ms 7.735 ms^C
每一跳会显示连续的三个RTT值。
分析策略
1、检查 络统计信息, 络包速率和 络接口吞吐量:ss、netstat、sar。
2、跟踪新TCP连接的建立和时长来分析负载:tcplife。
3、跟踪TCP重传和其他的不常见TCP事件:tcpretrans、tcpdrop、skb:kfree_skb跟踪点。
4、测量DNS延迟,这可能是一个性能问题,如:gethostlatency。
5、测量各维度的 络延迟,如连接延迟、首字节延迟、软件栈各层之间的延迟等。注意,如有可能, 络延迟测试应该在负载和空闲 络中分别测试,进行比较。
6、检查主机之间的 络吞吐量上限,同时检查在已知负载情况下发生的 络事件。
7、使用高频CPU性能分析抓取内核调用栈信息,以量化CPU资源在 络协议和驱动程序之间的使用情况。
8、使用跟踪点和kprobes来探索 络软件栈的内部情况。
常见问题
TIME_WAIT存在的2MSL的意义
在TCP实现中,每个 文的最大生存时间为MSL,2MSL则表示,一个 文在一个连接中,一来一回的时长。它存在的意义主要是,1、保证最后一个ACK,已经到达到远端。2、保证连接(客户端IP和端口,服务端IP和端口)只能在2MSL后才能使用。
TIME_WAIT过多
从TCP状态转换图可知,TIME_WAIT状态的出现,是由于主动断开连接导致的。也就是说,应用程序中存在大量的短连接,因此,解决TIME_WAIT过多的方法是,找出短连接的业务逻辑,将其修改为长连接。当然,如果应用程序作为服务端,主动断开了大量连接,可能需要结合业务作进一步分析断开原因。
可能还有的解决方案是,修改系统参数:tcp_tw_reuse、tcp_tw_recycle和tcp_max_tw_buckets,这三个参数的含义是:
使用修改tcp_tw_reuse和tcp_tw_recycle参数的方式,本身是有风险的,并不符合TCP协议规范。它可能导致延时的 文与新连接混在一起。尤其是tcp_tw_recycle参数,在NAT 络中,可能会导致SYN 文丢弃。可参考RFC 1122中关于TIME_WAIT重用的处理。
CLOSE_WAIT过多
当应用程序收到对端发过来的FIN 文,而未调用close()函数时,会在被动关闭一方,出现CLOSE_WAIT状态。因此,当出现大量CLOSE_WAIT状态时,通常是应用程序,未及时调用close()关闭连接。更进一步分析,可以看看,应用程序在处理对端连接关闭请求时是否有问题,还是Recv-Q有堆积。
Recv-Q和Send-Q堆积
判断当前连接状态是,Established还是Listening,然后,分析应用程序,是堵塞在收发数据包阶段,还是取连接的阶段。
TCP中KeepAlive与HTTP中keep-alive区别
参考
《Systems Performance:Enterprise and Cloud》
《BPF Performance Tools》
《Computer Systems》
《Modern Operating Systems》
《TCP/IP详解 卷1:协议》
http://www.brendangregg.com/linuxperf.html
https://datatracker.ietf.org/doc/html/rfc1122
https://vincent.bernat.ch/en/blog/2014-tcp-time-wait-state-linux
声明:本站部分文章及图片源自用户投稿,如本站任何资料有侵权请您尽早请联系jinwei@zod.com.cn进行处理,非常感谢!