我们的 PHP 网站上不断出现类似的错误。
无法连接到‘192.168.100.85’上的 MySQL 服务器 (4)
web 是 web 服务器 192.168.1.116
mysql 是 mysql 服务器 192.168.100.85
因此,我在 Web 服务器上编写了一个脚本,用于连续建立 10,000 个 mysql 连接并计时。它“有时”会产生错误。大多数时候,一切都运行正常,调用 mysql_connect 的平均时间为 5-10 毫秒
认真的谷歌搜索表明,(4)错误是由于连接因超时而切断。
web# grep mysql.connect_timeout /etc/php.ini
mysql.connect_timeout = 1
所以我将脚本中的超时时间修改为 30,看看是否可行。连接错误消失了,但偶尔连接需要 5 秒。
在谷歌搜索和使用 tcpdump 后,我发现 MySQL 服务器偶尔在反向查找 IP 时 DNS 服务器无法响应。因此,5 秒后它会放弃并允许连接。
此后,我已将 skip-name-resolve 添加到服务器。但这并没有解决问题。
现在我的测试显示连接速度很慢,需要 3-4.5 秒,而不是因 DNS 问题而设定的 5 秒。
因此我再次使用 tcpdump 在两端运行测试。
web# tcpdump -n -s 65535 -w web3-$(date +"%F_%H-%M-%S").pcap 主机 192.168.100.85 和端口 3306
mysql# tcpdump -n -s 65535 -w master1-$(date +"%F_%H-%M-%S").pcap 主机 192.168.1.116 和端口 3306
这是来自相关慢速连接的数据包。
来自网络的数据包:
No. Time Source Destination Protocol Info
13312 2010-10-13 10:01:01.201965 192.168.1.116 192.168.100.85 TCP 41560 > mysql [SYN] Seq=0 Win=5840 Len=0 MSS=1460 TSV=904829062 TSER=0 WS=2
13316 2010-10-13 10:01:04.201577 192.168.1.116 192.168.100.85 TCP 41560 > mysql [SYN] Seq=0 Win=5840 Len=0 MSS=1460 TSV=904832062 TSER=0 WS=2
13317 2010-10-13 10:01:04.204837 192.168.100.85 192.168.1.116 TCP mysql > 41560 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1380 TSV=562240314 TSER=904832062 WS=7
13318 2010-10-13 10:01:04.204853 192.168.1.116 192.168.100.85 TCP 41560 > mysql [ACK] Seq=1 Ack=1 Win=5840 Len=0 TSV=904832065 TSER=562240314
13319 2010-10-13 10:01:04.205886 192.168.100.85 192.168.1.116 MySQL Server Greeting proto=10 version=5.0.77-log
13320 2010-10-13 10:01:04.205899 192.168.1.116 192.168.100.85 TCP 41560 > mysql [ACK] Seq=1 Ack=61 Win=5840 Len=0 TSV=904832066 TSER=562240316
13321 2010-10-13 10:01:04.205959 192.168.1.116 192.168.100.85 MySQL Login Request userexample
13322 2010-10-13 10:01:04.206800 192.168.100.85 192.168.1.116 TCP mysql > 41560 [ACK] Seq=61 Ack=71 Win=5888 Len=0 TSV=562240317 TSER=904832066
13323 2010-10-13 10:01:04.206874 192.168.100.85 192.168.1.116 MySQL Response OK
13324 2010-10-13 10:01:04.208823 192.168.1.116 192.168.100.85 MySQL Request Quit
13325 2010-10-13 10:01:04.208839 192.168.1.116 192.168.100.85 TCP 41560 > mysql [FIN, ACK] Seq=76 Ack=72 Win=5840 Len=0 TSV=904832069 TSER=562240317
13326 2010-10-13 10:01:04.210422 192.168.100.85 192.168.1.116 TCP mysql > 41560 [FIN, ACK] Seq=72 Ack=76 Win=5888 Len=0 TSV=562240320 TSER=904832069
13327 2010-10-13 10:01:04.210437 192.168.1.116 192.168.100.85 TCP 41560 > mysql [ACK] Seq=77 Ack=73 Win=5840 Len=0 TSV=904832071 TSER=562240320
13328 2010-10-13 10:01:04.210567 192.168.100.85 192.168.1.116 TCP mysql > 41560 [ACK] Seq=73 Ack=77 Win=5888 Len=0 TSV=562240320 TSER=904832069
来自mysql的数据包:
No. Time Source Destination Protocol Info
13315 2010-10-13 10:01:04.204817 192.168.1.116 192.168.100.85 TCP 41560 > mysql [SYN] Seq=0 Win=5840 Len=0 MSS=1380 TSV=904832062 TSER=0 WS=2
13316 2010-10-13 10:01:04.204836 192.168.100.85 192.168.1.116 TCP mysql > 41560 [SYN, ACK] Seq=0 Ack=1 Win=5792 Len=0 MSS=1460 TSV=562240314 TSER=904832062 WS=7
13317 2010-10-13 10:01:04.206611 192.168.1.116 192.168.100.85 TCP 41560 > mysql [ACK] Seq=1 Ack=1 Win=5840 Len=0 TSV=904832065 TSER=562240314
13318 2010-10-13 10:01:04.206808 192.168.100.85 192.168.1.116 MySQL Server Greeting proto=10 version=5.0.77-log
13319 2010-10-13 10:01:04.207658 192.168.1.116 192.168.100.85 TCP 41560 > mysql [ACK] Seq=1 Ack=61 Win=5840 Len=0 TSV=904832066 TSER=562240316
13320 2010-10-13 10:01:04.207815 192.168.1.116 192.168.100.85 MySQL Login Request user=example
13321 2010-10-13 10:01:04.207872 192.168.100.85 192.168.1.116 TCP mysql > 41560 [ACK] Seq=61 Ack=71 Win=5888 Len=0 TSV=562240317 TSER=904832066
13322 2010-10-13 10:01:04.207910 192.168.100.85 192.168.1.116 MySQL Response OK
13323 2010-10-13 10:01:04.210817 192.168.1.116 192.168.100.85 MySQL Request Quit
13324 2010-10-13 10:01:04.210849 192.168.100.85 192.168.1.116 TCP mysql > 41560 [FIN, ACK] Seq=72 Ack=76 Win=5888 Len=0 TSV=562240320 TSER=904832069
13325 2010-10-13 10:01:04.211632 192.168.1.116 192.168.100.85 TCP 41560 > mysql [FIN, ACK] Seq=76 Ack=72 Win=5840 Len=0 TSV=904832069 TSER=562240317
13326 2010-10-13 10:01:04.211640 192.168.100.85 192.168.1.116 TCP mysql > 41560 [ACK] Seq=73 Ack=77 Win=5888 Len=0 TSV=562240320 TSER=904832069
13327 2010-10-13 10:01:04.213243 192.168.1.116 192.168.100.85 TCP 41560 > mysql [ACK] Seq=77 Ack=73 Win=5840 Len=0 TSV=904832071 TSER=562240320
如您所见,web 在 3 秒无响应后重新发送了初始 ACK。但 mysql 甚至从未看到过该初始数据包。
我还尝试运行 ping 泛洪来检查是否有丢包。如果让它运行的时间足够长,就会发现有丢包的情况。
web3# ping -f 192.168.100.85
PING 192.168.100.85 (192.168.100.85) 56(84) bytes of data.
....................................................................
--- 192.168.100.85 ping statistics ---
38253 packets transmitted, 38185 received, 0% packet loss, time 460851ms
rtt min/avg/max/mdev = 0.880/3.430/66.904/8.015 ms, pipe 7, ipg/ewma 12.047/1.378 ms
这个问题很不常见,但总是在发生。我确实知道简单地增加我们的超时时间会有很大帮助,但我更希望连接始终快速,并且永远不会在提供页面时出现 3-4 秒的延迟。
我联系了我们的托管服务提供商,他们说这可能是 Nagle 算法和延迟 ACK 之间不良交互的结果。http://www.stuartcheshire.org/papers/NagleDelayedAck/
我觉得好像有数据包被丢弃了。有什么办法可以更好地向托管人员证明这一点吗?38,000 个数据包中丢掉 60 个数据包似乎有点小问题。我应该忍受这种情况吗?
感谢您花时间研究这个问题!
答案1
我不会尝试使用 ping 泛洪,但我会设置一个连续流并让它运行,比如说 2 分钟。这是对网络“丢失”的更有效测试 - 有时 ping -f 可能会超出特定设备的范围并给出不可靠的结果。