1

我们最近将我们的一个网络服务器从 PHP 5.3(Debian Squeeze 软件包,使用 libmysqlclient 和 APC)升级到 PHP 5.4(Debian Wheezy,Dotdeb 软件包,使用 mysqlnd、Opcache 和 APCu)。在正常工作了将近一天之后,每个请求我们都遇到了“mysql server has gone away”错误。所有其他负载相同的服务器仍然运行 PHP 5.3 和 libmysqlclient 使用相同的 MySQL 服务器完全没有问题。在我们使用的所有服务器上:

max_execution_time = 60
default_socket_timeout = 60

在我们的 PHP 5.3 服务器上,我们没有更改任何 mysql/my.cnf 超时。我们知道 read_timeout (mysql)、wait_timeout (mysql)、default_socket_timeout (php) 和 max_execution_time (php) 的问题,但仅限于具有长时间运行查询的批处理脚本的上下文中。我们的网络服务器通常会在 300 毫秒左右做出响应,所以这些超时在这里应该不是问题。

当我们从负载平衡中删除服务器时,它变得非常奇怪,所以不再有负载,但我们仍然有 180 个繁忙的 Apache 进程。即使aapache2ctl graceful没有改变任何东西,甚至几个小时后apache2ctl status说:

                       Apache Server Status for localhost

   Server Version: Apache/2.2.22 (Debian)
   Server Built: Jun 16 2014 03:51:14
     __________________________________________________________________

   Current Time: Tuesday, 22-Jul-2014 10:17:44 CEST
   Restart Time: Monday, 21-Jul-2014 18:43:37 CEST
   Parent Server Generation: 26
   Server uptime: 15 hours 34 minutes 6 seconds
   Total accesses: 596973 - Total Traffic: 1.6 GB
   CPU Usage: u6288.72 s463.96 cu.01 cs0 - 12% CPU load
   10.7 requests/sec - 30.8 kB/second - 2962 B/request
   176 requests currently being processed, 99 idle workers

GGGGGG_GGGGGGGGG_GG_GGGGGGGGGGGGGGGGGGGG_GGGGGG_GGGGGGGG_GGGGGGG
GGGGGGGGGG_G_GGGGGGGG_G_GG__GGGGGG_GGGGG_GGG___GG_GGGGGGGG_G_GGG
GGGGGGGGGGGG_G_GG__GG_GGG_GGGGGGGGG__GGG_GGG_G_G_GG_G_GGGGGGGGGG
GGG_GGG_GG_GGG_GG_G_GGG_______________.___._W___________________
____.___________.______.........................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
................................................................
....

   Scoreboard Key:
   "_" Waiting for Connection, "S" Starting up, "R" Reading Request,
   "W" Sending Reply, "K" Keepalive (read), "D" DNS Lookup,
   "C" Closing connection, "L" Logging, "G" Gracefully finishing,
   "I" Idle cleanup of worker, "." Open slot with no current process

apache2ctl restart解决了这个问题,一切都恢复正常了。MySQL 错误是我们目前发现的唯一“有用”的错误消息。

可能是 mysqlnd、opcache 或 apcu 和 PHP 5.4.30 的问题吗?是否有任何已知问题可能导致我们所经历的行为?

或者您知道如何调试“mysql 服务器已消失”问题?

4

1 回答 1

0

我们大概找到了为什么会出现“mysql server has gone away”错误:在MySQL服务器上我们配置了a wait_timeout30 seconds,也就是小于60 seconds max_execution_time。因此,在某些情况下,当我们从 MySQL 读取结果集时,似乎需要超过 30 秒的时间,因此服务器在我们仍在尝试从服务器获取数据时关闭了连接。这将我们引向下一个问题:

  1. 当我们在从 mysql 读取结果集的循环中时,哪个函数会消耗这么多时间?

  2. 为什么不apache2ctl graceful重新启动 Apache 进程,即使max_execution_time应该在 60 秒后中止脚本?

我认为这两个问题的答案都是 APCu 中的一个错误。因为如果我查看悬挂的 Apache 孩子,我会FUTEX_WAIT从 strace 中得到:

[pid 28354] futex(0x7f3a8c3d2094, FUTEX_WAIT, 69, NULL <unfinished ...>

如果我使用 gdb 查看这样的过程,它似乎挂在pthread_rwlock_wrlock(),我得到的是:

0x00007f3adcd18abd in pthread_rwlock_wrlock () from /lib/x86_64-linux-gnu/libpthread.so.0

好的,pthread_rwlock 用于在 APCu 中锁定,锁定机制的问题很好地解释了我们在这里看到的情况,因为我们肯定有代码通过 MySQL 结果集在循环内部读取/写入 APCu,如果有是锁定的问题(过去对我们来说 APC 也是一个问题)它可能需要 >30 和 <60 秒,所以我们看到的是 MySQL 错误。在这种情况下,APCu 的某些事情真的出错了,所以 php 脚本不能被中止max_execution_time,也不能被重新启动apache2ctl graceful

在 APCu 问题跟踪器中,我可以找到非常相似的问题: https ://github.com/krakjoe/apcu/issues/19

但我们发现了另一个提示。崩溃总是发生,当 APCu 中有大约 70k 个键时,它不依赖于 apc.shm_size,但我们发现我们的APCu 监控脚本产生“PHP 致命错误:允许的内存大小为 134217728 字节已用尽(试图分配78 字节)”在我们看到崩溃的同时在第 47 行调用 apcu_cache_info() 时出错。所以我们必须查看脚本为什么它消耗这么多内存,AFAIR id读取了所有用于计算内存碎片的数据,也许我们应该删除那部分......

但是我们过去在 APC 上遇到了很多问题,我们切换到 APCu/Opcache 只是因为我们在最新的 APC 和 PHP 5.4.30 中出现了 seg faults 并且上面提到的问题现在已经开放了一年。我们很高兴看到最近在yac上的活动,也许无锁是一个更稳定的选择。如果我们无法通过从监控脚本中删除问题来解决问题,我们将切换到本地 memcached 实例,它会更慢但我们知道它非常稳定。

于 2014-07-25T08:40:12.100 回答