常见的网络问题
小包问题也叫愚笨窗口综合症(Silly Window Syndrome)
常常会有这样的情况,应用层传递给TCP传输层的数据很小,要比TCP(20Bytes)+ IP(20Byte)头部的大小还要小,这样其实是一种浪费,我们把这样的问题叫愚笨窗口综合症,也叫小包问题。
延迟确认(Delayed ACK) 与 Nagle 算法
延迟确认是一种常见的TCP交互式场景策略,常见的例子(愚笨窗口综合症)就是SSH与远程服务器建立连接之后在命令行输入的每一个字母在发送方打开延迟确认的TCP选项之后,发送方发给接收方的网络包中如果除了确认收到报文之外没有什么信息需要回复给发送方,那么接收方就会等待一个超时的时间(TCP协议规定这个值应当小于500ms rfc1122 ,不同的操作系统中这个值有所不同)之后在回复确认报文。本质上是通过在网络信道中减少网络包的发送来优化网络。
Nagle算法是通过在发送方维护一个“buffer”,将发送包体大小积累到一个MSS之后发送网络包。
if there is new data to send then if the window size ≥ MSS and available data is ≥ MSS then send complete MSS segment now else if there is unconfirmed data still in the pipe then enqueue data in the buffer until an acknowledge is received else send data immediately end if end ifend if
本质上也是通过在信道中减少网络包的发送数量来优化网络传输。
听起来两种机制都是没有什么问题的,都是在解决特定环境下的特定问题。但是如果发送方开启了Nagle算法与此同时接收方也开启了延迟确认,在发送方出现write-write-read这样的报文组合的时候就有可能出现等待到一个延迟确认超时时间后的网络等待。
如何解决延迟确认与Nagle算法冲突的问题
两种思路:
- 在应用层,避免出现 write-wirte-read这样的网络调用
- 在传输协议层,在发送方关闭Nagle算法机制或者在接收方关闭DelayACK
对于关闭DelayedACK:
TCP_QUICKACKtcp_delack_min
# echo 1 > /proc/sys/net/ipv4/tcp_delack_min
RHEL - realtime tuning - Reduce TCP Delayed ack timeout
对于关闭 Nagle 算法:
在TCP连接选项中选择 TCP_NO_DELAY
网络包重传
协议中的重传场景:
超时重传
出现拥塞,当发送方的原包发出后经过一个RTO的超时等待时间后就会重传这个网络包。
超时重传之后,拥塞窗口(发送窗口)的大小也需要调整,协议中建议 cnwnd = min ( traffic_in_flight / 2, 2)。
快速重传
如果接收方收到一组乱序的网络包,按照协议它应当连续发送3个重复ack,当发送方收到这样的ACK后需要启动快速重传机制。
具体细节详见下面wireshark抓包分析截图:
网络包乱序
接收方收到乱序包需要根据协议发送重复的3个ACK确认包,随后发送方会有快速重传的机制将接收方的ACK包重传,而无视RTO的超时限制。
细节参见上方快速重传Wireshark抓包分析截图。
网络传输慢速
慢启动与网络拥塞点
计划使用FTP协议传输大文件,进行网络抓包分析,得出类似下面的 time/sequence graph(steven):
// TODO
TCP发送窗口
LRO(Large Recieve offload)
WireShark 如何解决
查看超时重传的方法
Analysis -> Expert information
Note 类信息中Summary 部分为 “this frame is a (suspected) retransmission “
使用Wireshark自动分析
- 查看分析的摘要信息
Analysis -> Expert information
- 选定需要查看的TCP连接,查看TCP stream Graph 等统计信息
Statistics -> TCP Stream Graph
Time-Sequence Graph(steven)
有用的几个WireShark配置
常用的几个网络命令
- 使用ICMP发送指定大小的网络包(macOS)
ping -s -D -c
其中 -D 参数表示 在 IP 包中flag设置中 DF(Don’t Fragment) 标志
- WireShark中列出超过200ms的ack报文(查询疑似延迟确认报文)
tcp.analysis.ack_rtt>0.1 and tcp.len==0
文中名词解释
MSS(Maximum Segment Size)
TCP的3次握手会将双方的MSS值告诉对方,将MSS值加上TCP头和IP头的长度就知道了下面的MTU的大小。
MTU(Maximum Trasmission Unit)
MTU = MSS + TCP Head length(一般是20Bytes) + IP Head leagth(20Bytes)
通常的大多数网络中MTU的大小在 1500 Bytes,而开启了巨帧(Jumbo Frame)的网络MTU的大小在 9000 Bytes。