PHP CPU 和内存使用
PHP CPU and Memory Usage
我正在学习 PHP 和 Laravel。我工作的公司有一个纯 PHP 构建的网络应用程序。我注意到,当从 CPU 和内存密集型的大型 CSV 文件执行数据库更新之类的操作时,Web 应用程序几乎无能为力。例如,用一些无关紧要的东西更新某人的帐户,而不是 CPU 并且根本不会占用内存。基本上做前者会使系统变砖,直到它完成。查看 Linux 服务器上的 TOP
,显示 CPU 使用率接近 99%,内存使用率相当高。
无论如何,这真的不是一个类似企业的系统,只是一些用户用来管理另一个 Web 应用程序的用户,这些应用程序是在客户使用的 Python 框架中编写的。但这让我想到了基于 PHP 的企业系统的方法是什么?
显然不能让单个用户执行密集型任务,直到完成为止。我想在现实世界中有大量示例,其中 PHP 正在处理非常复杂的内存密集型任务,并且其他用户不会注意到它。
编辑:当我说 "bricking the system" 时,我指的是服务器本身,因此管理员 PHP 网络应用程序和客户端 Python 网络应用程序实际上都不响应请求。
在企业系统中,首先要处理的是冗余。一切都必须是多余的。对于基于 PHP 的应用程序,设置至关重要。
如果我们谈论的是网站,这些是步骤
DNS 已更新,因此它解析了 1 个以上的 IP。这样,将哪个 IP 返回给浏览器或者 DNS 池中的其中一台服务器是否先死掉都无关紧要。我们使用亚马逊的 Route 53。而且太棒了。
接下来是网络服务器。当 IP 为 "hit" 时,请求到达 Web 服务器。我们使用 nginx
(因为 nginx
是 - 你猜对了 - 很棒)。由于 DNS 池中有多个 IP 地址,因此有多个 Web 服务器可用。同样,哪个 Web 服务器将处理客户端的请求是无关紧要的 - 获胜的冗余。
nginx
要么提供静态内容,要么在满足规则时将请求传递给 PHP。我们使用 php-fpm
。 nginx
个服务器中的每一个都将 HTTP 请求代理到 php-fpm
个节点的集群。在常规语言中 - 它选择计算机集群中的另一台计算机为 PHP 提供服务。哪个 PHP 节点将处理请求是无关紧要的 - 获胜的冗余。
PHP 现在做一些工作,连接到数据库——你猜对了——它 "speaks" 到一个数据库集群。数据库是同步的,这方面的书很多,我就不赘述了。同样,哪个数据库获得查询并不重要 - 获胜的冗余(实际上有很多方法可以解决这个问题)。
数据库服务器针对它们正在进行的工作类型进行了优化 - 这意味着它们针对读取或写入进行了优化。数据库或任何类型的存储解决方案都不是可以像那样填充的无限黑洞。您必须仔细选择服务器要做什么——它会写吗?会用来读书吗?它会写多少次?它会读取多少次?工作量增加的计划是什么?基本上,您需要优化数据库服务器 - 您肯定 不能 使用默认 MySQL 配置。如果您有大量的工作负载可能会使数据库负担过重,您可以使用一种排队机制,该机制能够整理多个插入并在单个事务中刷新它们 - 该方法利用硬盘的带宽并将其折衷为 I/O(基本上,这意味着它很好并且运行速度很快)。
好了,好了。这是一个简短的概述,您将如何在 PHP 中接近企业级的东西。每个部分都应该是冗余的、水平可扩展的并且针对它正在做的工作类型进行了优化。
您绝对不希望您的应用在有人搞砸时挂起或变得无法使用。
我敢打赌我所有的 Quatloos,你有一个打开的会话,用于执行数据库插入的长 运行 请求,这会阻止后续请求打开会话。您需要做的是:
<?php
session_start();
/* pre-game stuff that depends on $_SESSION */
session_write_close();
/* long-running stuff that doesn't need to update $_SESSION */
或者如果可能的话,最好跳过打开此任务的会话。
附录:
- 解雇创建该 956 列、仅 varchar 数据库模式的人。
- 如果插入这么慢,我敢打赌有人离开了并且添加了太多索引。
- 如果您 运行 使用最便宜的共享 CPU、public 云实例,您很可能会用完所有 CPU 份额.我已经通过将大文件写入快速磁盘来红线了 GCE 微型实例的 CPU。
不应在 Web 请求上执行高要求流程。
例如,您应该采用的方法是使用队列。
这样,您允许文件上传并创建一个队列进程来为它服务,然后请求完成,进程在服务器上启动后片刻,但用户收到了请求。
那么你可以考虑配置低CPU优先级的队列,或者你可以在数据处理之间增加休眠时间,让CPU服务于其他进程。
或者您可以改为在上传文件后记录文件,并将控制台作业配置为每分钟检查一次是否有待处理的数据,然后处理一批并允许下一批在下一分钟处理检查,在某处处理当前行。
但是,同样,尽量避免在网络请求上做那种冗长的繁重过程,使用网络请求获取信息,然后单独触发过程。
Laravel 对框架中的控制台作业或队列有很好的支持。
我正在学习 PHP 和 Laravel。我工作的公司有一个纯 PHP 构建的网络应用程序。我注意到,当从 CPU 和内存密集型的大型 CSV 文件执行数据库更新之类的操作时,Web 应用程序几乎无能为力。例如,用一些无关紧要的东西更新某人的帐户,而不是 CPU 并且根本不会占用内存。基本上做前者会使系统变砖,直到它完成。查看 Linux 服务器上的 TOP
,显示 CPU 使用率接近 99%,内存使用率相当高。
无论如何,这真的不是一个类似企业的系统,只是一些用户用来管理另一个 Web 应用程序的用户,这些应用程序是在客户使用的 Python 框架中编写的。但这让我想到了基于 PHP 的企业系统的方法是什么?
显然不能让单个用户执行密集型任务,直到完成为止。我想在现实世界中有大量示例,其中 PHP 正在处理非常复杂的内存密集型任务,并且其他用户不会注意到它。
编辑:当我说 "bricking the system" 时,我指的是服务器本身,因此管理员 PHP 网络应用程序和客户端 Python 网络应用程序实际上都不响应请求。
在企业系统中,首先要处理的是冗余。一切都必须是多余的。对于基于 PHP 的应用程序,设置至关重要。
如果我们谈论的是网站,这些是步骤
DNS 已更新,因此它解析了 1 个以上的 IP。这样,将哪个 IP 返回给浏览器或者 DNS 池中的其中一台服务器是否先死掉都无关紧要。我们使用亚马逊的 Route 53。而且太棒了。
接下来是网络服务器。当 IP 为 "hit" 时,请求到达 Web 服务器。我们使用
nginx
(因为nginx
是 - 你猜对了 - 很棒)。由于 DNS 池中有多个 IP 地址,因此有多个 Web 服务器可用。同样,哪个 Web 服务器将处理客户端的请求是无关紧要的 - 获胜的冗余。nginx
要么提供静态内容,要么在满足规则时将请求传递给 PHP。我们使用php-fpm
。nginx
个服务器中的每一个都将 HTTP 请求代理到php-fpm
个节点的集群。在常规语言中 - 它选择计算机集群中的另一台计算机为 PHP 提供服务。哪个 PHP 节点将处理请求是无关紧要的 - 获胜的冗余。PHP 现在做一些工作,连接到数据库——你猜对了——它 "speaks" 到一个数据库集群。数据库是同步的,这方面的书很多,我就不赘述了。同样,哪个数据库获得查询并不重要 - 获胜的冗余(实际上有很多方法可以解决这个问题)。
数据库服务器针对它们正在进行的工作类型进行了优化 - 这意味着它们针对读取或写入进行了优化。数据库或任何类型的存储解决方案都不是可以像那样填充的无限黑洞。您必须仔细选择服务器要做什么——它会写吗?会用来读书吗?它会写多少次?它会读取多少次?工作量增加的计划是什么?基本上,您需要优化数据库服务器 - 您肯定 不能 使用默认 MySQL 配置。如果您有大量的工作负载可能会使数据库负担过重,您可以使用一种排队机制,该机制能够整理多个插入并在单个事务中刷新它们 - 该方法利用硬盘的带宽并将其折衷为 I/O(基本上,这意味着它很好并且运行速度很快)。
好了,好了。这是一个简短的概述,您将如何在 PHP 中接近企业级的东西。每个部分都应该是冗余的、水平可扩展的并且针对它正在做的工作类型进行了优化。
您绝对不希望您的应用在有人搞砸时挂起或变得无法使用。
我敢打赌我所有的 Quatloos,你有一个打开的会话,用于执行数据库插入的长 运行 请求,这会阻止后续请求打开会话。您需要做的是:
<?php
session_start();
/* pre-game stuff that depends on $_SESSION */
session_write_close();
/* long-running stuff that doesn't need to update $_SESSION */
或者如果可能的话,最好跳过打开此任务的会话。
附录:
- 解雇创建该 956 列、仅 varchar 数据库模式的人。
- 如果插入这么慢,我敢打赌有人离开了并且添加了太多索引。
- 如果您 运行 使用最便宜的共享 CPU、public 云实例,您很可能会用完所有 CPU 份额.我已经通过将大文件写入快速磁盘来红线了 GCE 微型实例的 CPU。
不应在 Web 请求上执行高要求流程。
例如,您应该采用的方法是使用队列。
这样,您允许文件上传并创建一个队列进程来为它服务,然后请求完成,进程在服务器上启动后片刻,但用户收到了请求。
那么你可以考虑配置低CPU优先级的队列,或者你可以在数据处理之间增加休眠时间,让CPU服务于其他进程。
或者您可以改为在上传文件后记录文件,并将控制台作业配置为每分钟检查一次是否有待处理的数据,然后处理一批并允许下一批在下一分钟处理检查,在某处处理当前行。
但是,同样,尽量避免在网络请求上做那种冗长的繁重过程,使用网络请求获取信息,然后单独触发过程。
Laravel 对框架中的控制台作业或队列有很好的支持。