加入收藏 | 设为首页 | 会员中心 | 我要投稿 PHP编程网 - 湛江站长网 (https://www.0759zz.com/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 教程 > 正文

一次简单的 HTTP 调用,为什么时延这么大?抓个包分析下

发布时间:2019-07-16 05:59:59 所属栏目:教程 来源:Java高级技术架构
导读:副标题#e# 1.最近项目测试遇到个奇怪的现象,在测试环境通过 Apache HttpClient 调用后端的 HTTP 服务,平均耗时居然接近 39.2ms。可能你乍一看觉得这不是很正常吗,有什么好奇怪的?其实不然,我再来说下一些基本信息,该后端的 HTTP 服务并没有什么业务逻

如果 A 向 B 发一个数据包,B 由于 Delayed ACK 不会立即响应。而 A 使用 Nagle 算法,A 就会一直等 B 的 ACK,ACK 不来一直不发送第二个数据包,如果这两个数据包是应对同一个请求,那这个请求就会被耽误了 40ms。

5.5 抓个包玩玩吧

我们来抓个包验证下吧,在后端HTTP服务上执行以下脚本,就可以轻松完成抓包过程。

  1. and 
  2.  host  
  3. 10.48 
  4. 159.165 
  5.  -s  
  6.  -w traffic.pcap 

如下图,这是使用 Wireshark 分析包内容的展示,红框内是一个完整的 POST 请求处理过程,看 130 序号和 149 序号之间相差 40ms(0.1859 - 0.1448 = 0.0411s = 41ms),这个就是 Nagle 与 Delayed ACK 一起发送的化学反应,其中 10.48.159.165 运行的是 Delayed ACK,10.22.29.180 运行的是 Nagle 算法。10.22.29.180 在等 ACK,而 10.48.159.165 触发了 Delayed ACK,这样傻傻等了 40ms。

一次简单的 HTTP 调用,为什么时延这么大?抓个包分析下

这也就解释了为什么测试环境耗时是 39.2ms,因为大部分都被 Delayed ACK 的 40ms 给耽误了。

但是本地复现时,为什么本地测试的平均时延是 55ms,而不是 ping 的时延 26ms?我们也来抓个包吧。

如下图,红框内是一个完整的 POST 请求处理过程,看 8 序号和 9 序号之间相差 25ms 左右,再减去网络延时约是ping延时的一半 13ms,因此 Delayed Ack 约 12ms 左右(由于本地是 MAC 系统与 Linux 有些差异)。

一次简单的 HTTP 调用,为什么时延这么大?抓个包分析下

  1. 1. Linux 使用的是 /proc/sys/net/ipv4/tcp_delack_min 这个系统配置来控制 Delayed ACK 的时间,Linux 默认是 40ms; 
  2. 2.MAC 是通过 net.inet.tcp.delayed_ack 系统配置来控制 Delayed ACK 的。 
  3. delayed_ack=0 responds after every packet (OFF) 
  4. delayed_ack=1 always employs delayed ack, 6 packets can get1 ack 
  5. delayed_ack=2immediate ack after 2ndpacket, 2 packets per ack (Compatibility 
  6. Mode) 
  7. delayed_ack=3should autodetect when to employ delayed ack, 4packets per ack. (DEFAULT)设置为 0 表示禁止延迟 ACK,设置为 1 表示总是延迟 ACK,设置为 2 表示每两个数据包回复一个 ACK,设置为 3 表示系统自动探测回复 ACK 的时机。 

5.6 为什么 TCP_NODELAY 能够解决问题?

TCPNODELAY 关闭了 Nagle 算法,即使上个数据包的 ACK 没有到达,也会发送下个数据包,进而打破 Delayed ACK 造成的影响。一般在网络编程中,强烈建议开启 TCPNODELAY,来提升响应速度。

当然也可以通过 Delayed ACK 相关系统的配置来解决问题,但由于需要修改机器配置,很不方便,因此,这种方式不太推荐。

6. 总结

(编辑:PHP编程网 - 湛江站长网)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!