Contents
  1. 1. 条件1
    1. 1.1. 在不中断请求的情况下
    2. 1.2. 在中断请求的情况下
  2. 2. 条件2
  3. 3. 条件3
    1. 3.1. 在不中断请求的情况下
    2. 3.2. 在中断请求的情况下
  4. 4. 条件4
    1. 4.1. 不中断情况下
    2. 4.2. 中断情况下
  5. 5. 总结

事情是这样,公司一个项目,使用浏览器访问时快速刷新页面会遇到问题,页面其中一个ajax请求过程比较长,快速刷新时该请求没有完成,请求会中断,nginx也没有收到该请求的日志,而且chrome(windows和mac)和firefox(windows)下的现象不一致,而在mac平台下firefox却没有问题,实践操作,分析一下这其中发生的事情。

首先模拟类似的场景,在本地虚拟机中创建 lnmp 环境,请求过程中直接 sleep 20 秒,使用 wireshark 抓包分析,查看 nginx 日志。

chrome和firefox默认情况下的请求头都带有Connection:keep-alive的标识,服务端也可以进行Connection的配置,表示了服务端接受或者拒绝keep-alive

条件1

在 mac 环境下使用 chrome 访问页面,服务端配置 持久性连接,即 connection:keep-alive。

在不中断请求的情况下

先进行TCP的三次握手,建立TCP连接(在0.001s内完成),客户端等待服务端响应,在前20s内nginx没有日志记录,在20s时完成http的response,nginx同时记录请求日志,状态码为200。

约86s时客户端发起了 TCP Keep-Alive,在196秒时,服务端发起了RST,tcp连接断开。

Nginx默认的Http keep-alive timeout是65s;

下图为wireshark的封包记录:

wireshark封包记录

在中断请求的情况下

同样先进行TCP的三次握手,建立TCP连接,这时刷新浏览器,nginx记录了日志,日志状态码为499,浏览器的网络状态是canceled,此时TCP连接依然是 ESTABLISHED 状态;中断请求时,服务端收到客户端的FIN包,但是连接依然是连接状态。在150s时服务端发起了RST,TCP连接断开。服务端收到FIN请求,自然不会再做出http响应,详见Wireshark封包记录。

在刷新浏览器后,连接依然会保持,由浏览器维持了这个连接,连接依然是可重用的,不需要重新建立。

Nginx 499 对应的是 “client has closed connection”,表示服务器返回http响应之前,客户端就提前关闭了http连接。

下图为wireshark的封包记录:

wireshark封包记录

条件2

在 mac 环境下使用 chrome 访问页面,服务端配置 非持久性连接,即 connection:close。

在非持久连接情况下,客户端不再发起 TCP Keep-Alive心跳包,而是正常经由发送FIN包由服务端time_wait=》close断开TCP连接。在中断请求的情况下,再刷新就是建立新的TCP连接了。

在中断请求的情况下,nginx记录一条状态码为499的日志记录。

下图为wireshark的封包记录:

wireshark封包记录

条件3

在mac环境下,使用Firefox访问页面,服务端配置 非持久连接。

在不中断请求的情况下

Wireshark显示即便在非持久连接的情况下,客户端发起了Keep-Alive心跳包(这是由于服务端sleep20s导致,客户端发起了心跳检测),每隔10s中发起一次Keep-Alive包。其他并无太大区别。

具体情况详见Wireshark抓包详图:

wireshark封包记录

在中断请求的情况下

没有出现FIN_WAIT2状态,直接由客户端关闭了TCP连接。

具体情况详见Wireshark抓包详图:

wireshark封包记录

条件4

mac环境下,使用Firefox访问页面,服务端配置 持久连接。

服务端没有发送RST包,而是由客户端发起的FIN包断开了TCP连接,其他并无太大不同;同样Keep-Alive还是每隔10s一次;具体见下图。

不中断情况下

wireshark封包记录

中断情况下

wireshark封包记录

总结

由于没有windows环境,就暂不进行分析了。由以上分析可见firefox和chrome在处理网络请求的一些细节上还是有很大的不同。

Contents
  1. 1. 条件1
    1. 1.1. 在不中断请求的情况下
    2. 1.2. 在中断请求的情况下
  2. 2. 条件2
  3. 3. 条件3
    1. 3.1. 在不中断请求的情况下
    2. 3.2. 在中断请求的情况下
  4. 4. 条件4
    1. 4.1. 不中断情况下
    2. 4.2. 中断情况下
  5. 5. 总结