2

我正在尝试从在外部 ubuntu 服务器上运行的 php 工作人员与 MySQL RDS 数据库建立持久连接。作为连接的一部分,我首先检查“mysql_ping”。如果 ping 返回 true,则使用当前连接,否则建立新连接。

我面临的问题是,当我启动我的工作人员时,连接建立良好,并且在一段时间内运行良好,即我可以成功地对 RDS 数据库进行重复查询。但是大约 15 分钟后,如果我提出请求,那么“mysql_ping”会挂起,因此 php 脚本本身也会挂起。在进一步调试中,我发现 mysql_ping 响应在 936 秒后返回为假。

从外部服务器访问 db 所需的权限在那里,并且在这段时间内(脚本挂起时),我能够使用 mysql 命令行选项成功连接到 RDS 数据库。另外,如果我杀死工人并重新启动它,它能够再次成功连接,但问题在 15 分钟左右后又回来了。

是否需要在 RDS 服务器设置中更改任何内容以避免此问题?

问候,卡皮尔

4

1 回答 1

3

我在文档中找不到引用,但我的经验表明 EC2 的网络基础设施一般(包括 RDS 和可能在按客户预置的虚拟机上运行的任何其他 AWS 服务,如果不是全部的话) AWS,当然似乎并不严格限于“EC2 实例”)实施状态数据包检查,并且会在几分钟的绝对空闲后“忘记”TCP 连接是有效的......导致您描述的行为。

连接两端的机器可能会确信连接仍然存在,但网络不允许它们之间的流量通过,因为 SPI 环境中的 TCP 会话未被发现,它们被创建,并且只能当网络在一开始就看到连接时创建(SYN、SYN/ACK、ACK)。我最初在 EC2(不是 RDS)中遇到 MySQL 服务器的这个问题,但如果根本原因不一样,我会非常惊讶。

有两种可能的方法来解决这个问题。

如果您的 PHP 机器是 Linux,请配置内核以在第 4 层保持连接处于活动状态。这种变化对您来说是不可见的,因为这些保持活动不会改变连接 inTime列中的值,因为它不会重置连接在第 7 层空闲的时间量......但如果管理 MySQL 连接的库正确设置套接字选项以利用它,它应该避免来自 AWS 基础设施的超时。SHOW PROCESSLISTSleep

http://tldp.org/HOWTO/TCP-Keepalive-HOWTO/usingkeepalive.html解释了如何实时设置,以及如何使其在重新启动后持续存在。

如果做不到这一点,另一种选择是强制 MySQL在网络超时之前关闭连接,以便 PHP 机器立即识别出它正在尝试在关闭的套接字上进行通信。缩短超时而不是延长超时可能听起来违反直觉,但是如果会话空闲时间过长,缩短超时应该会导致您的 ping 测试很快失败,这也(基本上)“解决”了问题,假设理智在 PHP 客户端库中。一旦您的应用程序更忙,连接可能很少会空闲足够长的时间来达到超时。

MySQL 服务器有两种不同的空闲超时设置:(wait_timeout对于非交互式会话,即来自代码的连接,如 PHP)和interactive_timeout(来自查询浏览器和命令行客户端)但服务器只知道区别,因为客户端库必须通知服务器正在建立哪种类型的连接。假设您的客户端库使用正确的设置,那么wait_timeout是你要找的那个。如果更改 Linux 内核中的 TCP keepalive 设置无法解决问题,请将其设置为低于 900 的值。但请注意,在进行更改后,只有未来的连接会受到影响——在进行更改时已经建立的连接仍将使用当前值运行,默认值为 8 小时(28800 秒)。这些可在您的实例的 RDS 参数组中进行配置。

此处的 AWS 文档中有类似行为的提示,以及需要调整的 Windows 注册表设置以更改 TCP keepalives 如果您在 Windows 上运行 PHP 服务器,而不是 Linux,正如我上面假设的那样......甚至尽管这篇文章专门关于 Redshift 和 EC2 外部的连接,但它似乎仍然验证了上面讨论的潜在问题。

于 2013-12-31T22:23:57.063 回答