系统平均负载极高

系统平均负载极高

我有一个网站,从上周开始在 VPS 上运行。从周一到周六,一切都很顺利。该网站每天有大约 4,500 名独立访客,平均负载和响应时间都很好。

周日,网站有大约 11,000 名独立访客,因为我们在当天提供独特且独家的内容。内容存储在 MySQL 数据库中,该数据库在不同的 VPS 服务器上运行并使用 InnoDB 引擎。这就是问题所在。由于访客数量的增加,平均负载将上升到极限,直到网站无法访问。

以下是顶部输出:

 This is an automated message notifying you that the 5 minute load average on your system is 238.37.
 This has exceeded the 10 threshold.

 One Minute      - 237.31
 Five Minutes    - 238.37
 Fifteen Minutes - 231.1

 top - 16:41:12 up 5 days, 18:51,  1 user,  load average: 238.68, 238.62, 231.25
 Tasks: 517 total, 246 running, 271 sleeping,   0 stopped,   0 zombie
 Cpu(s):  1.8%us,  0.3%sy,  0.0%ni, 97.6%id,  0.0%wa,  0.0%hi,  0.1%si,  0.2%st
 Mem:   3922920k total,  3542968k used,   379952k free,     2736k buffers
 Swap:  1048564k total,   105316k used,   943248k free,   142772k cached

 PID USER      PR  NI  VIRT  RES  SHR S %CPU %MEM    TIME+  COMMAND    
 14395 apache    20   0  313m  13m 4044 R  2.8  0.4   0:09.81 /usr/sbin/httpd -k start -DSSL
 13405 apache    20   0  314m  15m 4432 R  2.3  0.4   0:17.87 /usr/sbin/httpd -k start -DSSL
 15865 apache    20   0  312m  13m 4176 R  2.3  0.4   0:01.28 /usr/sbin/httpd -k start -DSSL
 15930 apache    20   0  310m  11m 4060 R  2.3  0.3   0:00.88 /usr/sbin/httpd -k start -DSSL
 15978 apache    20   0  310m  11m 4048 R  2.3  0.3   0:01.08 /usr/sbin/httpd -k start -DSSL
 16041 apache    20   0  309m  10m 4052 R  2.1  0.3   0:00.58 /usr/sbin/httpd -k start -DSSL
 16082 apache    20   0  211m 4192 2276 R  1.9  0.1   0:00.09 /usr/sbin/httpd -k start -DSSL
 14298 apache    20   0  310m  11m 4044 R  0.6  0.3   0:09.56 /usr/sbin/httpd -k start -DSSL
 14457 apache    20   0  311m  11m 4068 R  0.6  0.3   0:10.18 /usr/sbin/httpd -k start -DSSL
 14486 apache    20   0  310m  11m 4464 R  0.6  0.3   0:06.13 /usr/sbin/httpd -k start -DSSL
 15287 apache    20   0  313m  14m 4048 R  0.6  0.4   0:05.21 /usr/sbin/httpd -k start -DSSL
 15363 apache    20   0  310m  11m 4064 R  0.6  0.3   0:04.13 /usr/sbin/httpd -k start -DSSL
 15400 apache    20   0  313m  13m 4048 R  0.6  0.4   0:04.09 /usr/sbin/httpd -k start -DSSL
 15404 apache    20   0  310m  11m 4056 R  0.6  0.3   0:04.22 /usr/sbin/httpd -k start -DSSL
 15649 apache    20   0  313m  14m 4432 R  0.6  0.4   0:02.88 /usr/sbin/httpd -k start -DSSL
 15675 apache    20   0  310m  10m 4044 S  0.6  0.3   0:02.22 /usr/sbin/httpd -k start -DSSL
 15692 apache    20   0  310m  11m 4084 R  0.6  0.3   0:01.46 /usr/sbin/httpd -k start -DSSL
 15702 apache    20   0  311m  12m 4044 R  0.6  0.3   0:01.85 /usr/sbin/httpd -k start -DSSL
 15719 apache    20   0  310m  10m 4048 R  0.6  0.3   0:02.32 /usr/sbin/httpd -k start -DSSL
 15781 apache    20   0  318m  18m 4044 R  0.6  0.5   0:01.91 /usr/sbin/httpd -k start -DSSL
 15788 apache    20   0  312m  13m 4048 R  0.6  0.4   0:02.13 /usr/sbin/httpd -k start -DSSL
 15823 apache    20   0  310m  11m 4060 R  0.6  0.3   0:02.04 /usr/sbin/httpd -k start -DSSL
 15837 apache    20   0  311m  12m 4052 R  0.6  0.3   0:01.64 /usr/sbin/httpd -k start -DSSL

周日,该网站必须执行一个相当大的查询,并在不同的表上进行几个左连接。

网站运行在 VPS 上,包含 2 个 2.4 Ghz 处理器和 4GB 内存。数据库运行在 SSD VPS 上,包含 2 个 2.4 Ghz 处理器和 2GB 内存。

在那个特定的星期天,我还在服务器的 ErrorLog 中收到了此消息:

 Sun Nov 24 15:03:34 2013] [error] server reached MaxClients setting, consider raising the MaxClients setting

该网站是使用 PHP Codeigniter 框架创建的,在共享主机上运行良好(使用相同的代码)。几周后,问题开始出现,这就是我决定转移到 VPS 服务器的原因。但问题似乎还在继续。

我完全不知道事情到底出了什么问题,因此我将非常感激任何帮助。

答案1

你的问题的答案是尽可能地利用内存缓存。即memcache,varnish等......然后使用nginx,你可以水平扩展它,在它后面是一个适合你的负载大小的php-fpm池,与上游nginx盒完全啮合。

一旦达到一定的流量水平,解决问题就不再仅仅依靠硬件,而是利用缓存,并拥有可以单独升级/更新的各个层。

你不能在单个 vps 上拥有超高可用性站点,除非它是静态 html,即使那样 varnish 也是理想的。

获取一对 haproxy 前端负载均衡器,分发到 varnish,从 nginx / php / memcache / redis / mysql (postgres) 中提取数据.....简而言之就是这样 :P

答案2

MaxClients 是 Apache 服务器指令。有几个相关指令,但它们都以不同的方式设置 Apache 处理请求的限制。

这样做的目的是为了不让 Apache 消耗太多资源,从而威胁整个系统的稳定性。因此,如果您增加 MaxClients 和其他类似指令,则需要注意 RAM 等系统资源。

更多详情请阅读: MaxClients 指令

但首先,即使您发现了一些症状(很明显,否则您就不会发帖了),也不清楚问题到底出在哪里。Apache 可能向您展示了其他地方的问题。

但是在输出中您关注的是 Apache,因为那部分相当简单,所以让我们从那里开始。

正如您在链接中看到的,MaxClients 定义了 httpd 服务的最大请求数。当该值填满时,请求将在 ListenBackLog 中排队。当该值已满时,客户端将被拒绝。

  • 要么是因为同时的请求数量太多,maxclients 已经满了。然后你需要为此做些准备,这相对容易。在 Apache 层中向上和/或向外扩展,直到你处于安全状态,或者直到数据库层达到最大值。

  • 或者 maxclients 已满,因为底层无法快速提供服务。因此请求在 Apache 中堆积,直到不再接受。这同样不容易解决,因为它首先引发了大量问题。您立即将注意力集中在数据库层上,这可能是有充分理由的,即使您还没有完全弄清楚(目前)。

看看客户端是否被拒绝、拒绝了多少等等,这些也对你有利。如果你将页面状态代码提取到日志中,你可以解析...503,我似乎记得,但你应该用谷歌查一下。这只是为了了解你的交付情况,并设置一个基准,以便与下次发生的情况进行比较。

以下是我想到的一些问题。我意识到找到答案说起来容易做起来难,除非您拥有可以为您提供极高洞察力的工具。我们使用 Dynatrace(面向 Java),它非常昂贵,但可以在几分钟内回答这些问题,甚至对于系统管理员来说,它可以深入到代码中的组件级别。这使得可以快速确定代码、基础设施或两者结合中的因果关系。我知道市场上还有其他工具,也可能有开源替代品可以做到这一点。我只是没有使用它们的经验。我想人们也可以编写代码调试和应用程序日志来记录同样的事情,只是这会耗费更多的工作时间。

在您描述的错误累积期间,请求是否需要更长的时间来处理?我的 Apachelogs 显示了处理每个请求所需的时间。我不记得这是否是默认设置,但如果没有,您可以在本周初发布这样的指令。

如果他们确实花费了更长时间,是因为请求模式不同还是仅仅是因为数量更多?

就 Apache 服务器负载而言,您提供大量静态内容还是主要提供动态内容?您是否以某种方式设定了静态与动态的基准?这个问题很重要,因为静态内容可以分离到不同的交付服务器,也可以分离到 RAM 缓存(另一个答案中提到了 Varnish)。在某些交付中,节省的成本可能很大,而在其他交付中则不然。

是否有许多请求针对(本质上)相同的动态内容,还是每个请求都重新计算一次?换句话说,是否可以注入早期缓存层来捕获某些动态内容?

深入研究一下,代码处理起来是否繁重?能否使用主要触发逻辑但数据库调用相对较少的请求作为基准?也许是代码需要优化或扩展?

数据库调用在数量和查询方式上是否进行了优化或浪费?在高负载期间,每次呼叫的响应时间是多少?响应时间是否增加了?呼叫数量是否达到最大值?

您会看到它越来越接近数据库,在每一层都寻找优化、缓存、分发(扩展)、原始功率(扩大)的机会。

也许你已经有了所有这些答案,并且完全正确地将注意力集中在 innodb 上,我无法根据给出的信息来判断!我所能提供的只是系统性的问题,这些问题可能相关,也可能不相关,也可能引起共鸣 :-)

但尽快将 Apache 排除在外似乎是个好主意(因为它可能只是遭受附带损害)。如果您确实可以验证 Apache 不是根本原因,请关注应用程序以及它如何使用数据库。

所涉及机器的基本统计数据(例如网络 io、RAM 消耗、CPU 消耗、磁盘 io、页面错误等)也有助于研究。

相关内容