问题:连续向本地服务器发送180-200次请求后,客户端接收不到响应,超时取消重试后仍然收不到响应
解决思路:wireshark抓包分析客户端还是服务端问题,服务端问题让后端同学处理
1.安装wireshak
2.由于测试的是本地服务器,需要抓取loopback设备,有很多解决方法,我选择了安装npcap
3.开测!
打开wireshark,选择Adapter for loopback traffic capture
接着在在 Wireshark 中只筛选127.0.0.1:5000
的数据,也就是本地服务器的地址和端口。
在 Wireshark 的过滤器输入框中输入以下过滤表达式:
ini
ip.src == 127.0.0.1 && tcp.port == 5000 || ip.dst == 127.0.0.1 && tcp.port == 5000
这个表达式的含义是:筛选出源 IP 为127.0.0.1
且 TCP 端口为5000
的数据包,或者目的 IP 为127.0.0.1
且 TCP 端口为5000
的数据包。
这样设置后,Wireshark 将只显示与127.0.0.1:5000
相关的数据。
另外补充说明一下表达式中各部分的含义:
ip.src == 127.0.0.1
:表示源 IP 地址为127.0.0.1
。tcp.port == 5000
:表示 TCP 端口为5000
。||
:表示逻辑或操作符,用于连接两个条件,表示满足其中任意一个条件即可。ip.dst == 127.0.0.1
:表示目的 IP 地址为127.0.0.1
。
4.万事具备,启动
点击左上角开始抓包,接着启动客户端和服务端,复现问题,观察wireshark抓包数据和devtools的网络面版,耐心等待一会后,出现了图片中这种情况
我们先来了解一下客户端与服务端基于 TCP 协议进行通信的过程
markdown
1. 客户端向服务端发送 POST 请求:这表示客户端发起了与服务端的交互,使用 POST 方法通常是为了向服务器提交数据。
2. 服务端发送 ACK:服务端接收到客户端的请求后,发送 ACK(Acknowledgement,确认)表示确认收到了客户端的请求。ACK 报文的作用是向发送方确认数据已经成功接收。
3. 服务端发送 ACK 和 PSH:这里的 ACK 仍然是对之前客户端请求的确认。而 PSH(Push,推送)标志表示服务端希望将数据尽快推送给接收方(客户端)的应用程序,而不是在缓冲区中等待更多数据再发送。这意味着服务端在确认收到请求的同时,也准备好立即向客户端发送数据(例如响应内容)。
4. 客户端发送 ACK:客户端收到服务端的 ACK 和带有 PSH 标志的数据后,发送 ACK 给服务端,确认已经收到了服务端推送的数据。
5. 出现 HTTP 响应:这是服务端对客户端 POST 请求的实际响应,包含了请求的处理结果、数据等信息。HTTP 响应遵循特定的格式,客户端可以根据响应的状态码、头部信息和主体内容来进行相应的处理。
6. 客户端又发送一个 ACK:客户端再次发送 ACK 可能是为了对 HTTP 响应进行确认。在 TCP 协议中,ACK 确认是确保数据可靠传输的重要机制,通过不断的确认和重传,保证数据不丢失、不重复,并按序到达。
由以上可知,该问题请求是在第三步出现了问题,也就说**服务端发送 ACK 和 PSH:这里的 ACK 仍然是对之前客户端请求的确认。而 PSH(Push,推送)标志表示服务端希望将数据尽快推送给接收方(客户端)的应用程序,而不是在缓冲区中等待更多数据再发送。这意味着服务端在确认收到请求的同时,也准备好立即向客户端发送数据(例如响应内容)。**这一步有问题,至此问题排查完毕,联系后端同学,协助修改bug。
5.补充
为什么抓包最后会出现TCP Keep-Alive 的信息
TCP的Keep Alive TCP的Keep Alive的意图是在于保持TCP连接的存活,就是发送心跳包。隔一段时间给连接对端发送一个探测包,如果收到对方回应的 ACK,则认为连接还是存活的,在超过一定重试次数之后还是没有收到对方的回应,则丢弃该 TCP 连接。
再补充一点:
HTTP的Keep-Alive与TCP的Keep Alive,有些不同,两者意图不一样。HTTP的Keep-Alive主要是 TCP连接复用,避免建立过多的TCP连接。
arduino
在 HTTP/1.1 之前,如 HTTP/1.0 中,每个请求-响应都需要建立一个新的 TCP 连接,完成后立即关闭。这导致了大量的连接建立和关闭开销,特别是在需要发送多个请求获取多个资源的情况下,如一个网页可能包含图片、样式表、脚本等多个资源。
HTTP/1.1 的 Keep-Alive 机制改变了这一情况。它允许在一个 TCP 连接上发送多个请求和接收多个响应,减少了建立和关闭连接的次数,从而显著提高了性能。
在抓包中,如果看到与 Keep-Alive 相关的信息,通常会在 HTTP 请求和响应的头部中。常见的相关头部字段包括:
Connection: Keep-Alive:在请求或响应头部中明确指示使用持久连接。
Keep-Alive: timeout=5, max=1000:这指定了 Keep-Alive 连接的超时时间(timeout)和最大请求数(max)。超时时间表示在没有数据传输的情况下,连接保持打开的时间;最大请求数表示在该连接上允许发送的最大请求数量。
例如,如果一个网页包含多个资源,通过 Keep-Alive,客户端可以在同一个 TCP 连接上依次发送对这些资源的请求,而不必为每个请求都重新建立新的连接。服务器也可以在同一个连接上依次返回这些请求的响应。
这种机制减少了连接建立的三次握手和关闭连接的四次挥手所带来的延迟和资源消耗,特别对于包含大量小文件或资源的网页,能够显著提高页面加载速度和整体的网络性能。
然而,需要注意的是,虽然 Keep-Alive 改善了性能,但它仍然存在一些限制。例如,由于是在一个连接上顺序处理请求和响应,可能会导致队头阻塞(Head-of-Line Blocking)问题。这也是促使 HTTP/2 引入多路复用等新特性的原因之一。
后续
后端使用的是Flask和Gevent。 从
修改为
就解决了该问题。
希望有知道原理的大佬解释一下,万分感谢。