【问题标题】:PHP CPU and Memory UsagePHP CPU 和内存使用情况
【发布时间】:2016-09-09 22:59:58
【问题描述】:

我正在学习 PHP 和 Laravel。我工作的公司有一个纯 PHP 构建的 Web 应用程序。我注意到,在执行诸如从 CPU 和内存密集型的大型 CSV 文件执行数据库更新之类的操作时,Web 应用程序几乎无能为力。例如,用一些无关紧要的东西更新某人的帐户,而且根本不会占用 CPU 和内存。基本上做前者会使系统变砖,直到它完成。查看 Linux 服务器上的 TOP,显示 CPU 使用率接近 99%,内存使用率相当高。

无论如何,这确实不是一个类似企业的系统,只是一些用户用来管理另一个 Web 应用程序的用户,该应用程序是用客户使用的 Python 框架编写的。但这让我想到了基于 PHP 的企业系统的方法是什么?

在完成之前,显然不能让单个用户执行密集型任务来阻塞系统。我想在现实世界中有很多例子,PHP 正在处理非常复杂的内存密集型任务,而其他用户却不明显。

编辑:当我说“构建系统”时,我指的是服务器本身,因此管理员 PHP Web 应用程序和客户端 Python Web 应用程序都不会响应请求。

【问题讨论】:

  • CSV 文件大概有多大?数十兆字节..千兆字节?列的数据类型是什么?只需添加一个大数据列表,它应该很快..您是在让 SQL 执行任何逻辑还是简单的 INSERT INTO ...?我们需要查看代码才能知道为什么要花这么长时间。
  • 我目前使用的是大约 17MB,但是 SQL 正在做的是检查表中是否已经存在行,如果不添加它们。我没有写它,但在我看来应该删除该表并创建一个新表。看起来他们几乎制作了所有东西 VARCHAR(32)... 大约有 956 列和 5000 行。
  • 我希望它不要一一检查行。
  • 是的,我真的应该看看查询。尽管如此,有没有办法在不停止运行的情况下限制它正在使用的 CPU 和内存量,从而希望允许其他用户继续他们的工作?

标签: php laravel memory cpu


【解决方案1】:

在企业系统中,您首先要处理的是冗余。一切都必须是多余的。对于基于 PHP 的应用程序,设置至关重要。

如果我们谈论的是网站,这些是步骤

  • DNS 已更新,因此它可以解析超过 1 个 IP。这样,将哪个 IP 返回给浏览器或 DNS 池中的一个服务器是否首先死亡都无关紧要。亚马逊的 Route 53 是我们使用的东西。而且太棒了。

  • 接下来是 Web 服务器。当一个 IP 被“命中”时,请求就会到达一个 Web 服务器。我们使用nginx(因为nginx - 你猜对了 - 很棒)。由于 DNS 池中有多个 IP 地址,因此有多个 Web 服务器可用。同样,哪个网络服务器将处理客户端的请求是无关紧要的 - 获胜的冗余。

  • nginx 要么提供静态内容,要么在满足规则时将请求传递给 PHP。我们使用php-fpm。每个nginx 服务器将HTTP 请求代理到php-fpm 节点集群。在常规语言中 - 它在服务 PHP 的计算机集群中选择另一台计算机。哪个 PHP 节点将处理请求无关紧要 - 获胜的冗余。

  • PHP 现在做了一些工作,连接到数据库,并且——您猜对了——它与数据库集群“对话”。数据库是同步的,关于这个主题有整本书,所以我不会详细介绍。同样,哪个数据库获取查询无关紧要 - 获胜的冗余(实际上有很多方法可以处理这个问题)。

  • 数据库服务器针对它们正在执行的工作类型进行了优化 - 这意味着它们针对读取或写入进行了优化。数据库或任何类型的存储解决方案都不是您可以像那样填充的无限黑洞。您必须仔细选择服务器将要做什么——它会写吗?会用来读书吗?它会写多少次?它会读多少次?工作量增加的计划是什么?基本上,你需要优化数据库服务器——你肯定不能使用默认的 MySQL 配置。如果您有大量的工作负载可能会使数据库负担过重,您可以使用一种队列机制,该机制能够在单个事务中整理多个插入并刷新它们 - 该方法利用硬盘的带宽并将其用于 I/O(基本上,这意味着它很好,而且工作速度很快)。

那么,就这样吧。这是一个简短的概述,您将如何在 PHP 中处理企业级的东西。每个部分都应该是冗余的、水平可扩展的并针对其正在执行的工作类型进行优化。

您绝对希望您的应用在有人搞砸时挂起或无法使用。

【讨论】:

    【解决方案2】:

    不应在 Web 请求上执行高要求的过程。

    例如,您应该使用队列。
    这样,您允许文件上传并创建一个队列进程来提供服务,然后请求完成并且在服务器上进程启动后片刻,但用户收到了请求。

    那么你可以考虑将队列配置为低CPU优先级,或者你可以在数据处理之间增加睡眠时间,让CPU服务于其他进程。

    或者您可以在上传文件后记录文件,并配置控制台作业以每分钟检查是否有待处理的数据,然后处理一批并允许下一批在下一分钟检查时处理,将当前行处理在某处。

    但是,同样,尽量避免对 Web 请求执行那些冗长繁重的过程,使用 Web 请求获取信息,然后单独触发该过程。

    Laravel 对框架中的控制台作业或队列都有很好的支持。

    【讨论】:

      【解决方案3】:

      我敢打赌,我所有的 Quatloos 都认为您有一个开放会话,用于执行数据库插入的长期运行请求,这会阻止后续请求打开会话。你需要做的是:

      <?php
      session_start();
      
      /* pre-game stuff that depends on $_SESSION */
      
      session_write_close();
      
      /* long-running stuff that doesn't need to update $_SESSION */
      

      或者更好的是,如果可能的话,跳过为此任务打开会话。

      附录:

      1. 解雇创建 956 列、仅限 varchar 的数据库架构的人。
      2. 如果插入速度如此之慢,我敢打赌,有人已经离开并添加了太多索引。
      3. 如果您在尽可能便宜的共享 CPU 公有云实例上运行,您很可能会用完所有 CPU 份额。我只是通过将一个大文件写入快速磁盘来对 GCE 微型实例的 CPU 进行红线。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-10-15
        • 2011-01-17
        相关资源
        最近更新 更多