php - mysql_ping 与 Amazon RDS 一起挂起

标签 php mysql amazon-web-services rds

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

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

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

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

问候, 卡 PIL

最佳答案

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

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

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

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

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

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

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

hints of similar behavior in the AWS docs here ,以及如果您在 Windows 上运行 PHP 服务器(而不是像我上面假设的那样在 Linux 上运行),则需要调整 Windows 注册表设置以更改 TCP keepalives...尽管本文专门介绍 Redshift 和外部连接EC2 似乎仍然验证了上面讨论的根本问题。

关于php - mysql_ping 与 Amazon RDS 一起挂起,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20856599/

相关文章:

php - 只允许字母、数字、空格、逗号、句点的正则表达式?

php - 检索所有记录并从另一个数据库插入到另一个表

mysql - 向函数 st_geometryfromwkb 提供的 GIS 数据无效

ios - 如何将 AWS-S3 加密文件(AES-256 加密)读取到我的 IOS 应用程序中?

java - 如何实时定位 Alexa 设备?

php - 通过 JSON 将 javascript 数组发送到 php 不起作用

php - 如何使用 PHP 代码而不是 HTML 代码导入/包含 CSS 文件?

javascript - 如何在javascript中使用php代码

php - NOW() 函数在我的网络主机上返回错误的时间戳

amazon-web-services - 将 POST 请求从 CloudFront 路由到 Lambda