针对SQL服务器的TCP数据包丢失

针对SQL服务器的TCP数据包丢失

在我工作的地方,我们遇到了一些与数据库连接的问题。我们遇到了很多失败,在客户端显示为“recv failed”。我使用Wireshark尝试调试问题并取得了一些进展,但现在我几乎陷入困境。

首先,介绍一下基础设施:

  • 内部 IT 系统作为虚拟机(服务器)在 1-2 台物理机器上运行。它们由 Glassfish 上的多个应用程序以及一个 SQL 服务器组成。
  • 此外,还有一些外部提供商的服务器,包括这里的 SQL 服务器。
  • 内部系统和外部系统之间存在防火墙,用于路由流量。

问题在于内部区域的应用程序与外部区域的数据库之间的通信。该问题仅发生在部分虚拟服务器上(实际上当时只有一台),并且不是特定于应用程序的(它通过 Glassfish 和 JDBC 连接池以及 SQuirreL 等 SQL 客户端发生。)

而且,情况变得更加奇怪,因为运行了小的 SQL 语句,但是一旦它们达到一定长度,就不会发生任何事情,直到客户端关闭连接(接收失败)。

以下是我使用 Wireshark 发现的结果:

  • 在正常运行的服务器上,小型 SQL 查询在 Wireshark 中显示为单个 TDS 数据包,并带有直接 TDS 数据包响应(不显示 TCP 确认等)。大型查询通常首先作为 TDS 发送,然后部分作为 TCP 重新发送,正确确认,然后返回结果。(在一个案例中,我看到它首先尝试了 2400 字节 TDS,然后是 1514 字节 TCP,然后是 590 字节 TCP,并获得了最后一个的确认。)
  • 在无法正常工作的服务器上,小查询将作为 TDS 数据包发送(这有效)。另一方面,对于大查询,它首先尝试将整个查询作为 TCP 数据包发送,然后获得 seq 和 ack = 1 的 ACK(表示未收到数据?),然后尝试发送 1514 字节的 TCP 数据包,未收到任何 ACK。在连接断开之前,它会再尝试几次。
  • 如果 SQuirreL 中的最大结果是 ticket,它首先发送一个小的 TDS 数据包,说明对结果的限制,然后尝试发送查询,但只会收到第一个查询的重新发送确认。查询的重新发送不会收到任何确认。

我完全不知道下一步该看哪里,有人能指点一下吗?

更新:重新启动虚拟服务器可以解决问题 - 至少目前如此。

更新 #2:.. 现在问题又回来了..

答案1

我们请网络专家查看了这个问题,结果发现是错误的 MTU 设置导致了这个问题。据我所知,大多数网络基础设施都支持巨型帧,因此 MTU 设置为 9000。但有一个组件(VPN 隧道)不支持,因此超过一定大小的帧会被截断。将所有 MTU 设置更改为 1500/1460 解决了这个问题。

相关内容