页面挂起等待查询,消耗内存,需要 2 小时才能失败

页面挂起等待查询,消耗内存,需要 2 小时才能失败

请参阅随附的 Fusion Reactor 图片,其中显示了持续运行的页面。时间已达到数百万,我让它们等待是否完成,但那时只有 2 或 3 个。

现在我收到了几十页永远都无法完成的页面。而且这是不同的查询,除了似乎只适用于我的 7 个数据库中的 3 个之外,我看不到任何重大模式。

top节目冷融合CPU 使用率约为 70-120%,深入研究 Fusion Reactor 详细信息页面可以发现,所有构建时间都花在了 Mysql 查询上。

show processlist返回的内容没有任何异常,除了 10 - 20 个连接睡觉状态。

在此期间,许多页面确实完成了,但随着挂起的页面数量的增加,它们似乎永远无法完成,服务器最终只返回白页。

唯一的短期解决方案似乎是重新启动 Coldfusion,但这远非理想。

最近添加了一个 Node.js 脚本,该脚本每 5 分钟运行一次并检查要处理的批量 csv 文件,我想知道这是否会导致窃取所有 MySQL 连接的问题,所以我禁用了它(脚本中没有 connection.end() 方法)但这只是一个快速的猜测。

不知道从哪里开始,有人可以帮忙吗?

最糟糕的是页面永远不会超时,如果超时的话也不会那么糟糕,但过了一段时间就什么都没有了。

我正在运行 CentOS LAMP 堆栈,以 Coldfusion 和 NodeJS 作为我的主要脚本语言

永远不会失败的长请求

实际发布前更新

在撰写这篇文章的过程中,我禁用了 Node 脚本并重新启动 Coldfusion,问题似乎已经消失了。

但我仍然需要一些帮助来确定页面为什么不会超时,并确认 Node 脚本需要类似的东西connection.end()

而且它可能只会在负载下发生,所以我不能 100% 确定它已经消失了

更新

仍然有问题,我刚刚复制了 Fusion Reactor 中目前最多需要 70 秒的查询之一,并在数据库中手动运行它,它在几毫秒内就完成了。查询本身似乎不是问题。

另一更新

其中一个页面的堆栈跟踪仍在运行。服务器已经有一段时间没有停止提供页面了,所有 Node 脚本目前都已禁用

http://pastebin.com/D6ycJf3X

更多更新

我今天又做了几个这样的工作——它们实际上已经完成了,并且我在 FusionReactor 中发现了这个错误:

Error Executing Database Query. The last packet successfully received from the server was 7,200,045 milliseconds ago. The last packet sent successfully to the server was 7,200,041 milliseconds ago. is longer than the server configured value of 'wait_timeout'. You should consider either expiring and/or testing connection validity before use in your application, increasing the server configured values for client timeouts, or using the Connector/J connection property 'autoReconnect=true' to avoid this problem.

更多更新

在代码中挖掘时,我尝试寻找“2 小时”、“120”和“7200”,因为我觉得 7200000ms 的超时太过巧合。

我找到了这个代码:

// 3 occurrences of this
createObject( "java", "coldfusion.tagext.lang.SettingTag" ).setRequestTimeout( javaCast( "double", 7200 ) );

// 1 occurrence of this 
<cfsetting requestTimeOut="7200">

引用这些代码行的 4 个页面很少运行,从未出现在 2 小时以上超时的日志中,并且位于受密码保护的区域,因此无法被抓取(它们用于文件上传和 CSV 处理,现在已移至 nodejs)。

这些设置是否可能以某种方式由一个页面设置但存在于服务器中,并影响其他请求?

答案1

1)发布堆栈跟踪。

我保证他们会挂在 Socket.read() 上(或类似方法)

发生的情况是,到数据库的 1/2 tcp 连接被关闭,导致 cf 等待永远无法得到的响应。

cf 盒和 db 之间存在网络问题。

Java db 驱动程序通常不能很好地处理这个问题


感谢堆栈跟踪

这证实了我的假设,即 1/2 的 TCP 连接正在关闭。

我怀疑是以下原因之一:1)mysql 在 linux 上,而 TCP 堆栈中有一个错误,因此您需要升级该机器上的 linux - 是的,我之前见过这种情况;2)coldfusion 在 linux 上...按照 1);3)两个机器上或之间有电缆/硬件故障;4)如果您运行的是 windows,请禁用 TCP OFFLOAD!!!

第三个问题比较难。您需要在两个盒子上运行 wireshark 并证明数据包丢失。更简单的解决方案是将 Rackspace VM 移动到不同的物理主机并查看它是否消失。(您的代码非常糟糕并且您在 CF 盒和 MySQL 盒之间的网络中造成饱和的可能性很小,但我不确定是否可能编写出如此糟糕的代码)

答案2

我花了更多时间研究这个问题,并补充了一些有关网络问题具体原因的详细信息,并在 Charlie Arehart 的帮助下找到了解决方法。

首先,网络连接被触发的自动脚本中断iptables restart。这会更新可访问服务器的 IP 地址列表,但也会中断应用程序和数据库服务器之间的任何连接。

这更有可能发生在速度较慢的页面或运行更频繁的页面上,但与iptables restart代码相符的任何东西都会被切断。

Rackspace 为我找到了这个问题并建议更改代码:

/sbin/service iptables restart

/sbin/iptables-restore < /etc/sysconfig/iptables

这将停止重新启动服务并且仅适用于新的连接。

这是问题的根本原因,但真正的问题是 Coldfusion 或实际上底层的 JDBC 不会停止等待来自 DB 服务器的响应。

我不确定 2 小时超时是从哪里来的(假设它是默认值)但 Charlie 展示了一种在 CFIDE 连接字符串中设置较低超时的方法 - 这告诉 CF 在放弃 DB 之前等待最长时间。

所以我们的连接字符串是:

__fusionreactor_name=datasourcename;connectTimeout=600000;socketTimeout=600000;

我不记得这两个的具体细节,但它们设置了以毫秒为单位的时间来等待,然后放弃数据库连接:

  • 连接超时=600000;
  • 套接字超时=600000;

这一步只是在 Fusion Reactor 中标记数据源 - 如果您有它,它对于查找 CF 应用程序中的问题非常有用。如果您没有 Fusion Reactor,请忽略这部分。

  • __fusionreactor_name=dsnapi;

你必须将其应用于 CFIDE 中的每个数据源

CFIDE 数据源面板显示连接字符串

相关内容