Nginx + php-fpm - 运行时每个 php-fpm 进程占用 70-100% CPU

Nginx + php-fpm - 运行时每个 php-fpm 进程占用 70-100% CPU

我遇到了以下情况:

  • 我们使用的是 8 核、8GB RAM、2.6GHz 的 linode - 使用 nginx + php-fpm - 我们得到了极高的 CPU 使用率图表(我们不希望它成为如此糟糕的 VPS 邻居)...

  • 我们网站上同时只有不到 100 个用户,因此这种情况也非常尴尬,因为我们的 CPU 使用率非常高。

  • 我们正在使用一个非常未知的、可能占用大量 CPU 的 php 框架,这是一个非常糟糕的框架,而不是像 wordpress 或 drupal 等其他知名、有据可查、制作精良的框架,其中有大量关于在 nginx + php_fpm 平台上缓存(以及处理缓存的插件)php 的文档。

  • 因此,我们有大约 6 个打开的 php-fpm 进程,它们在运行时分别消耗大量(30% 以上,通常接近 99%)的 CPU - 而我真的不知道如何阻止它们使用这么多的 CPU。我无法分辨哪些 php 脚本导致了这些峰值,因为它们一直在发生……通常只有 1 个或 2 个在运行 - 但是当所有 6 个都运行时,我们会最大化所有 8 个 CPU。

  • 我的pool.d/www.conf文件有以下设置:

    pm = dynamic
    pm.max_children = 10
    pm.start_servers = 4
    pm.min_spare_servers = 2
    pm.max_spare_servers = 6
    
  • 我们这样做了 ^ 设置,因为按照我的解释,我们的内存实际上是惊人的(htop 显示使用了 472/7000+mb,没有交换等),我们可以处理更多的进程并打破等待处理的队列 - 但不幸的是,由于每个进程在运行时对我们的 CPU 来说都太过紧张 - 我们最终导致 CPU 超负荷 - 因此我们无法处理足够的进程。

  • 问题- 我们到底能做什么减少 php-fpm 进程的 CPU 使用率,以便我们可以增加该池配置文件中 php-fpm 的设置- 而且是的,/var/log/php5-fpm.log 正在向我们大喊大叫,要求我们增加子进程并调整/增加最小/最大/启动服务器。但这样做会使我们的负载平均值变得疯狂,如前所述。我们如何才能在不使用缓存的情况下做到这一点,或者我们有哪些选择?

  • 我的想法?我读过关于使用 cpulimit 来确保没有进程占用超过分配的 CPU 量的文章 - 但这会减慢速度以至于无法使用吗?或者这样做我们可以提高运行多个进程的能力 - 我也想过运行两个池 - 一个用于我们的面向前端的网站(客户体验),另一个用于后端(当运行耗时的报告时,这会影响我们的面向前端的网站)。

  • 我花了几天时间研究、谷歌搜索等关于这个主题的内容 - 这很困难,因为每个人的情况都与他们的体系非常不同 - 问题在于,采用这种特定的、闻所未闻的、可能写得不好的框架很难找到解决方案。我们也不能就此放弃这个框架 - 我必须找到某种解决方案。


更新:我已经实现了 memcache 来存储 php 会话 - 因为该框架严重依赖于用户会话,并且我们系统的性质是员工通常同时使用多个选项卡 - 每个选项卡都会检查会话以确认能力/用户数据/等等...所以我希望看到性能有所提升 - 如果您愿意,欢迎对此发表评论 - 明天当我们度过更高的峰值时段时,我会看看情况如何。

答案1

需要考虑以下几点(如果您已经考虑过这些,请提前致歉):首先,确保优化您的 nginx 配置,并且仅在绝对必要时才调用 php-fpm。您最不想做的事情就是让 php 处理静态 HTML 页面之类的事情(它很乐意这样做)。

其次,由于您使用的是 php-fpm,我建议对 php-fpm 子进程的存活时间进行更严格的限制。您需要在短暂存活的线程/子进程和稳定性之间找到最佳平衡点。在我看来,php-fpm 的默认值对于任何生产系统来说都太慷慨了。允许工作进程处理请求的时间越长,它就会变得越不稳定。内存泄漏的风险也更高,如果您提到的这个框架有无限循环之类的错误,这可能会让您对 CPU 负载感到苦恼,这应该不会有什么坏处。

我会减少生产池的数量pm.max_requests。我认为默认值是 200。我会从 50 开始,看看结果如何。

如果失败/补充这一点,您还可以尝试这些全局选项(据我所知,它们默认情况下都是禁用的):

emergency_restart_threshold 3
emergency_restart_interval 1m
process_control_timeout 5s

这是什么意思?如果 1 分钟内有 3 个 PHP-FPM 子进程以 SIGSEGV 或 SIGBUS 退出(即崩溃),则 PHP-FPM 应该会自动重新启动。子进程等待 5 秒,等待主进程对信号做出反应。

以下是我在这里提到的所有配置选项以及其他选项的概述:http://myjeeva.com/php-fpm-configuration-101.html

希望这些技巧能帮到你!记得调整和观察,不幸的是,这一切似乎没有经验法则,正如你所观察到的,有太多变量会影响 PHP 的行为和稳定性。

最后,您询问的 CPU 限制功能已记录在案这里,但我只会在您用尽所有其他选项时才会诉诸它。如果您确实选择了这条路,我肯定会注意 PHP-FPM 调整和您的 limits.conf 配置之间可能存在的交互。那时etckeeper可能会救命!:)

祝你好运!

鲁本

答案2

您正在运行操作码缓存,对吗?

以前这里使用的是 APC,但是它已经有一段时间存在缺陷了,所以已经被Zend Opcache,它从 PHP 5.5 开始就成为 PHP 的一部分,并且在 PECL 5.3 和 5.4 中有反向移植。

相关内容