遇到的问题及现象

项目提出一个变更:上传文件超出 Tomcat 配置的最大大小后,优化客户端报错信息 ,问题改起来不难,但在改的过程中却发现另外一个问题(本文档探索的问题),当超出最大大小后客户端在一些情况下收不到返回信息,所以报错 (failed)ERR_CONNECTION_RESET
当时配置文件配置为:

 spring.servlet.multipart.max-file-size = 10KB
 spring.servlet.multipart.max-request-size = 10KB
  1. 实验发现当小于 3M 时浏览器客户能为正常收到返回值,但是一旦超过 4M,浏览器客户端则显示 (failed)ERR_CONNECTION_RESET

  2. 服务端能够在 HandlerExceptionResolver(全局异常捕捉类) 中捕获到异常并能正常流程返回给客户端

  3. 当开着 http 抓包工具 Fiddler 时,则问题消失,无论多大的文件都能正常收到返回值

工具介绍

Fiddler

Fiddler 是一个 HTTP 协议调试代理工具,它能够记录并检查所有你的电脑和互联网之间的 http 通讯,设置断点,查看所有的进出 Fiddler 的数据(指 cookie , html , js , css 等文件)

Fiddler 工作原理

浏览器与服务器之间通过建立 TCP 连接以 HTTP 协议进行通信,浏览器默认通过自己发送 HTTP 请求到服务器。 而 Fiddler 是 c# 开发的 http 代理服务器,Fiddler 工作于七层中的应用层,能够捕获到通过的 http(s) 请求。Fiddler 启动后会自动将代理服务器设置为本机,端口是 Fiddler 监听端口。监听的端口号在 Fiddler 菜单 Tools - options - connections 中可以修改。数据传递流程大致如下:

Fiddler

Wireshark

Wireshark 是用来获取网络数据封包,可以截取各种网络封包,显示网络封包的详细信息,包括 http,TCP,UDP ,等网络协议包。注: Wireshark 只能查看封包,而不能修改封包的内容,或者发送封包。(官方下载网站: http://www.Wireshark.org/)

  • 抓包后的窗口界面:

    Wireshark

  • Wireshark 与对应的 OSI 七层模型:

    OSI

  • 从下图可以看到 Wireshark 捕获到的 TCP 包中的每个字段:

    TCP包具体内容

问题探索过程

寻找问题的思路

  1. 因为是否开启 Fiddler 会影响到最后浏览器是够能获取到 response ,针对这个特点对服务端代码的流程进行对比

  2. 使用 Wireshark 进行 TCP 层面的监控,看到底是哪一步出现异常

问题流程

  1. 首先利用对比在开启 Fiddler 和不开启 Fiddler 的情况下对比服务端的执行流程,发现细微异常,开启 Fiddler 时是在 finishResponse() 方法中返回页面数据,关闭 Fiddler 时是在关闭 Socket 链接时 upload 请求变成 failed 。但是区别不大,也无法定位问题

  2. 后来决定使用 Wireshark 进行 tcp 层面的研究

    1. 将 Wireshark 增加过滤器,只看 TCP 和 8080 端口(本地端口)

      Wireshark1

    2. 关闭 Fiddler 时,上传一个 18M 文件,可以发现在 Wireshark 出现了两千多帧,右键某一帧找到追踪流下的 TCP 流,或者选中某一帧使用快捷键 Ctrl+Alt+Shift+T ,就可以看到该 TCP 的整个流程

      Wireshark2

    3. 该页面包含的各部分信息可以在上面 Wireshark 简介里面了解,在界面下方可以选择整个对话还是客户端发给服务端的对话或者是服务端发给客户端的对话。

      Wireshark3

    4. 然后我们发现服务端发给客户端的信息中已经包含了服务端封装好的异常,也就是问题不是出在服务端而是客户端,且 response 信息在整个 TCP 流程的中间部分,也就是客户端只上传了部分文件服务端就返回了 reponse ,但是客户端却还在一直上传。 reponse 在整个 TCP 流程的中间。

      Wireshark4

    5. 然后我们打开 Fiddler , Wireshark 过滤器改为 tcp port 8888 ( 8888 端口为 fiddler 使用的端口)进行监听,发现 reponse 在整个 TCP 流程的最后。

      Wireshark5

    6. 最后通过现象发现问题还是应该出在客户端,所以再尝试试了一下第三个浏览器 Edge 浏览器,发现一切正常,问题是出在浏览器身上

总结

  1. 关于更换浏览器一开始就尝试过了,但是 Chrome 和 Firefox 都不行,当时认为第三个浏览器正常的可能性太小;

  2. 通过 Wireshark 发现 TCP 流程是正常的,所以可以排除了服务端,问题就在客户端,所以才想到再次尝试更换 Edge 浏览器

  3. 关于为什么 Chrome 和 Firefox 不行的原因,我们通过是否开启 Fiddler 的前后对比不难猜出,是因为客户端还在向服务端传输数据包,但是服务端 Tomcat 先通过头信息的 Content-Length (文件大小)判断是否超出配置的最大文件大小,如果超出了直接就返回 reponse 了,但是客户端还在发送信息包,所以就出现了 reponse 在整个 TCP 流程的中间的现象;此时 Chrome 和 Firefox 浏览器无法接收到返回信息, Edge 浏览器比较聪明可以获取到返回值。小于 3M 的文件因为在本地传输速度比较快,所以服务端还未处理完异常信息文件已经传输结束,所以 reponse 在整个 TCP 流程的最后,所以所有浏览器都不出现问题

附:TCP 知识点补充

三握四挥: https://blog.csdn.net/catttbao/article/details/70173057

Logo

一站式 AI 云服务平台

更多推荐