【问题标题】:PHP waiting for curl to finish before returningPHP 在返回之前等待 curl 完成
【发布时间】:2018-01-06 00:58:16
【问题描述】:

我有两个 PHP 文件,一个用于“重载”,一个用于快速响应,将请求编组到重载,以便快速响应文件可以立即响应服务器请求(至少,这是目标)。这样做的前提是 Slack Slash 命令更喜欢即时 200 让用户知道命令正在运行。

<?php
echo("I want this text to reply to server instantly");
ini_set('display_errors', 1);
ini_set('display_startup_errors', 1);
error_reporting(E_ALL);
$code = '200';

$curl = curl_init();
curl_setopt_array($curl, array(
  CURLOPT_URL => "http://myheavyliftingfile.php",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_ENCODING => "",
  CURLOPT_MAXREDIRS => 10,
  CURLOPT_TIMEOUT => 30,
  CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => "datatobeusedbyheavylifter:data",
  CURLOPT_HTTPHEADER => array(
    "cache-control: no-cache",
    "content-type: application/x-www-form-urlencoded",
    "postman-token: 60757c65-a11e-e524-e909-4bfa3a2845fb"
  ),
));

$response = curl_exec($curl);
?>

似乎正在发生的事情是,我的响应/回显在我的heavylifting.php curl 完成之前不会发送到Slack,即使我希望我的响应立即发生,而繁重的过程本身是分开的。如何让一个 PHP 文件确认请求,启动另一个文件上的另一个进程,并在不等待漫长的进程完成的情况下做出响应?

更新

我不希望一次运行多个卷曲,我只想执行一个卷曲但不等待它返回以便向 Slack 返回一条消息说我收到了请求。我的 curl 将数据发送到我的另一个执行繁重工作的 php 文件。如果这仍然是重复中定义的问题,请随时再次标记它,我不会重新打开。

【问题讨论】:

  • 您是否尝试过在开始 curl 语句之前刷新输出缓冲区? php.net/manual/en/function.ob-flush.php
  • 嗨 ivanivan,刚刚尝试刷新缓冲区但无济于事。谢谢@barmar,关于标记的dupe的问题,这将允许我同时执行多个curl请求,但它是否允许我在每个curl请求完成之前向服务器返回200?如果是这样,那么是的,这是一个骗局,如果不是,那么我的问题可能会略有不同。我不希望创建多个 curl 并让它们同时执行,我希望在启动 curl 请求后返回,而不是等待它完成,因为我的其他 php 文件会处理它。
  • 这只是同一件事的一个更简单的例子。执行多个请求而不等待它们完成与执行一个请求而不等待它完成有什么区别?
  • 其实我看到了这个问题。该解决方案使用线程,但我认为在所有线程完成之前主脚本不会完成。因此,如果您根本不想等待,则需要另一种解决方案。
  • 谢谢 Barmar,是的,我相信这就是我遇到的问题,我不想等待,而不是想通过一次运行多个卷发来节省时间。抱歉,一开始还不清楚。也许我正在寻找的东西在 PHP 中是不可能的,但我想我会检查一下。

标签: php asynchronous slack


【解决方案1】:

这不起作用的原因是 PHP curl 调用始终是同步的,并且您的超时设置为 30 秒,这远远超过了最大值。斜杠命令允许的 3 秒。

但是有一个修复程序可以使这项工作。您只需要这些小改动:

  1. 将 curl 超时设置为较小的值,以确保您的第一个脚本在 3 秒阈值以下完成,例如将CURLOPT_TIMEOUT_MS 设置为 400,它定义了 400 毫秒的超时时间。

  2. 在您的第一个脚本中将 CURLOPT_NOSIGNAL 设置为 1。这是超时在基于 UNIX 的系统中工作所必需的。

  3. 确保在您的第一个脚本中忽略超时错误(CURL ERROR 28),因为您的 curl 应始终返回超时错误。

  4. 通过添加以下行确保您的第二个脚本不会因强制超时而中止:ignore_user_abort(true);

有关完整示例,另请参阅 this answer

P.S.:这种方法不需要任何缓冲区刷新。

【讨论】:

  • 非常有帮助,谢谢 Erik,您的方法非常有效。谢谢
猜你喜欢
  • 2020-05-13
  • 2016-05-08
  • 2021-06-20
  • 1970-01-01
  • 1970-01-01
  • 2019-06-11
  • 2020-04-17
  • 1970-01-01
  • 2021-12-02
相关资源
最近更新 更多