异步 PHP 执行
Posted
技术标签:
【中文标题】异步 PHP 执行【英文标题】:Asynchronous PHP execution 【发布时间】:2013-05-14 21:22:00 【问题描述】:我尝试通过 API 对字段值进行大规模更新,但我遇到了 php 脚本的最长执行时间。
我将我的工作划分为较小的任务,以便将它们作为较小的工作异步运行......
Asynchronous PHP calls?
我找到了这篇文章,它看起来不错,但是 cmets 有点令人反感... 使用 curl 运行外部脚本文件会阻止调用方文件触发最大执行时间,还是 curl 仍会等待来自服务器并杀死我的页面?
真正的问题是:如何在 PHP 中执行异步作业?类似于 Ajax。
编辑::///
有一个项目管理工具,其中包含大量数据行。 我正在使用这个工具 API 来访问数据行并将它们显示在我的页面上。 使用我的工具的用户将使用复选框选择多行数据,然后在框中键入新值。 然后用户将按下运行更新脚本的“更新行值”按钮。
此更新脚本将可能选择的数百或数千个项目分成 100 个组。
此时我打算使用一些异步方法联系项目管理工具并更新所有 100 项。
因为在更新这些项目时,该服务器可能需要很长时间才能运行其进程,我需要确保拆分这些作业的原始页面不再等待来自该操作的请求,以便我可以触发更多更新项目的请求。并允许我的服务器页面对我的用户说“好的,当前正在更新,可能需要一段时间,一旦完成,我们会发送一封电子邮件”。
$step = 100;
$itemCount = GetItemCountByAppId( $appId );
$loopsRequired = $itemCount / $step;
$loopsRequired = ceil( $loopsRequired );
$process = array();
for( $a = 0; $a < $loopsRequired; $a++ )
$items = GetItemsByAppId( $appId, array(
"amount" => $step,
"offset" => ( $step * $a )
) );
foreach( $items[ "items" ] as $key => $item )
foreach( $fieldsGroup as $fieldId => $fieldValues )
$itemId = $item->__attributes[ "item_id" ];
/*array_push( $process, array(
"itemId" => $itemId,
"fieldId" => $fieldId,
) );*/
UpdateFieldValue( $itemId, $fieldId, $fieldValues );
// This Update function is actually calling the server and I assume it must be waiting for a response... thus my code times out after 30 secs of execution
//curl_post_async($url, $params);
【问题讨论】:
使用队列/工作者系统! AMQP、ZeroMQ、Gearman 等都是你的朋友。 通过命令行启动它们对您来说是一个可行的选择吗? 这是需要自动化的东西,并且长度可变。有些工作可能一次需要 5 分钟...老实说......我不完全确定这是否是一个可行的解决方案 对于队列系统,有什么不需要额外扩展的吗?我无法控制我当前所在的服务器。 那你有问题了。如果您需要运行长时间的作业,标准的共享主机 Apache-only Web 服务器是一个不好的平台。 【参考方案1】:根据您的实现方式,可以使用异步 PHP 将 Web 请求与处理分离,从而将 Web 请求与处理中的任何超时隔离开(但您可以在单个线程中执行相同的操作)。将任务分解成更小的并发部分会使其运行得更快吗?可能不会 - 通常这会延长完成工作所需的时间 - 只有当你拥有非常大的处理能力并且可以有效地分配任务时(例如 map-reduce )。 HTTP 调用 (curl) 是一种分配此类工作的有效方式吗?不。还有其他方法,包括同步和异步消息传递、批处理、进程分叉、线程……每种方法都有自己的优点和复杂性——我们不知道您要解决的问题是什么。
因此,即使在我们回答您的具体问题之前,这看起来也不是一个好策略。
将使用 curl 运行外部脚本文件防止调用者文件触发最大执行时间
它将受到目标服务器上配置的任何超时的约束 - 如果它与调用脚本是同一台服务器,那么它将是相同的超时。
curl 是否仍会等待服务器的响应并终止我的页面?
我不知道你在这里问什么 - 这意味着存在你没有告诉我们的功能依赖关系。
听起来您已经选择了一个解决方案,现在正在尝试使其适合您的问题。
【讨论】:
您的瓶颈很可能是数据库 - 将工作分片以并行运行不会使其运行得更快。在网络服务器之外调用繁重的列表将避免超时问题(symcbean.blogspot.co.uk/2010/02/…),但有更好的方法 - 例如用户与其交互后立即更新每一行,限制 UI,使其一次不能更新超过 100 行(并多路复用查询)。【参考方案2】:如果您使用的是 PHP-CLI,请尝试使用 Threads,或使用非线程安全版本使用 fork()。
【讨论】:
如果我在新线程上少量解雇我的工作,这将停止最大执行? 不会的。您需要 set_time_limit(0) 以便脚本可以无限期地继续。然而,这背后有一个完整的机制,你如何传递消息,你如何构建回复等等,仅仅使用线程或分叉进程本身不会做太多事情。您应该像 deceze 所说的那样研究作业队列,否则您最终会自己制作(使用线程或分叉进程)。 非常感谢.. 很大的帮助。以上是关于异步 PHP 执行的主要内容,如果未能解决你的问题,请参考以下文章