群里看到大神写的一篇文章说一次普通的http调用耗时很高,然后分析了是因为Nagele算法和Delayed ACK结合导致的。看完之后突然想起之前用spring cloud测试不同服务之间接口调用耗时没啥逻辑但耗时就是有几十毫秒的耗时,恍然大悟,可能也是因为文章说的这个原因导致的。原文地址:简单的 HTTP 调用,为什么时延这么大?
Nagle算法
Nagle算法是为了减少网络数据包的发送来提升网络效率的一种算法。http接口调用使用的是http协议,http协议属于应用层协议,发送的数据都会加上下层的tcp和ip协议头。比如我们只有1个字节的数据要发送,也会加上tcp协议头(20字节)+ip协议头(20字节)+1字节数据本身,这种有效载荷是及其低下的,于是就可以用Nagle算法来提升有效载荷,所以Nagle算法是为了处理小报文段数据发送的问题,是应用在tcp协议层,Nagle算法有以下几个特性:
- 发送的内容大于1个MSS(max segment size)即最大报长度,一般是1460个字节,就立即发送。
- 发送之前,没有包未被ack,则立即发送
- 发送之前,如果缓冲区有包未被ack,则把要放的内容缓存起来
- 收到ack,立即发送缓存内容
java可以通过设置启动参数-Dsun.net.httpserver.nodelay=true来关闭 Nagle算法,Apache HttpClient 默认都是开启的Nagle算法的。
TCP Delayed ACK
TCP Delayed ACK是为了提升网络数据包的发送效率而采取的一种手段。TCP协议为了保证数据传输的可靠性收到了一个数据包就会回应一个ACK位表示确认收到数据包。只是单纯的发送一个确认就需要发送40个字节(20字节TCP协议头+20字节IP协议头),于是为了提升网络效率,就会将几个数据包的响应组合在一起为单个响应或者将ACK响应与数据一起发送给对方,从而减少协议开销。
TCP Delayed ACK有以下几个特性:
- 当有响应数据时,会随着响应数据一起发送给对方
- 当没有响应数据时,会延迟发送,等待有响应数据时一起发送。等待超时时间Linux系统默认是40ms
- 等待ACK发送期间,对方的第二个包到达了,这时要立即发送ACK.但是对方的第三个数据包相继到达,这时候是否立即发送ACK,取决于上面的两条。
网友评论