【问题标题】:sending a non-blocking HTTP POST request发送非阻塞 HTTP POST 请求
【发布时间】:2009-10-12 16:22:37
【问题描述】:

我有两个网站,分别是 php 和 python。 当用户向服务器发送请求时,我需要 php/python 向远程服务器发送 HTTP POST 请求。我想立即回复用户,而无需等待远程服务器的响应。

是否可以在向用户发送响应后继续运行 php/python 脚本。在这种情况下,我将首先回复用户,然后才将 HTTP POST 请求发送到远程服务器。

是否可以在 php/python 中创建一个非阻塞的 HTTP 客户端而不处理响应?

在 php 和 python 中具有相同逻辑的解决方案对我来说更可取。

谢谢

【问题讨论】:

标签: php python nonblocking


【解决方案1】:

在 PHP 中,您可以通过发送此请求来关闭连接(这与 HTTP 相关,并且在 python 中也可以使用,尽管我不知道要使用的正确语法):

// Send the response to the client
header('Connection: Close');
// Do the background job: just don't output anything!

附录:我忘了提到您可能必须设置“上下文长度”。另外,请查看this comment 以获取提示和真实测试用例。

示例:

<?php    
ob_end_clean();
header('Connection: close');

ob_start();

echo 'Your stuff goes here...';

header('Content-Length: ' . ob_get_length());

ob_end_flush();
flush();

// Now we are in background mode
sleep(10);
echo 'This text should not be visible';    
?>

【讨论】:

  • 它将如何在框架中工作?例如在 MVC 框架中?我必须将它作为框架本身的一部分作为最后一步,还是我可以只在其中一个控制器中使用它?
  • 我不知道你的用例。如果您需要在后台执行 new 操作,我会将整个框架包含在 ob_start()...ob_end_flush() 对中。但在这里我猜。 MVC 对我来说是一个空词……不过,更好的候选人应该是控制器。
  • 这对我不起作用......在测试脚本中,在我放置标题('Connection:Close')之后,我放置了一个睡眠(5)。当我在浏览器中点击它时,它还在睡觉。我错过了什么吗?
  • @ContextSwitch:您应该阅读答案中链接的评论。无论如何,我提供了一个例子。
  • @ntd 谢谢,我错过了链接的评论
【解决方案2】:

您可以生成另一个进程来处理对另一台服务器的 POST。在 PHP 中,您将生成进程并“断开连接”,因此您无需等待响应。

exec("nohup /path/to/script/post_content.php > /dev/null 2>&1 &");

然后你可以卷曲来执行帖子。如果要将参数传递给 PHP 脚本,可以使用 getopt() 函数来读取它们。不确定你是否会在 Python 中做类似的事情。

【讨论】:

  • 使用 exec 需要大量资源并且会很慢。
【解决方案3】:

您需要做的是让 PHP 脚本执行另一个执行服务器调用的脚本,然后向用户发送请求。

【讨论】:

  • 是的,您可以通过 exec() 或 cURL 执行此操作。您不是在启动线程,而是在启动另一个脚本,该脚本独立于您处理用户响应的脚本运行。
  • 因此,如果 exec() 太慢,只需通过 cURL 执行即可。使用辅助脚本需要发送到远程服务器的用户请求中的任何数据向另一个脚本发出发布请求。设置辅助脚本以使用“知道了,谢谢”来响应您的主脚本,然后让它继续运行。
【解决方案4】:

你必须设置一个中间人。因此,在您自己的服务器中,您将拥有:

  • 一个网络表单;
  • 提交处理程序(处理表单提交的 php 或 python 脚本);
    • 您的处理程序创建一个新文件并用提交数据填充它。例如,您可以将数据格式化为 JSON;
    • 因此,您的处理程序只有一个作业,将提交的数据保存在文件中并响应用户,仅此而已。这应该很快。
  • 创建文件系统事件驱动的 cron(不是时间驱动的 cron)。请参阅 thisthis 问题(分别适用于 windows 和 ubuntu 服务器)。
    • 设置您的 cron 以执行 php 或 python 脚本,然后将数据重新发布到远程服务器。

【讨论】:

    【解决方案5】:

    您必须使用 fsockopen。并且不要听结果

    <?php
    
    $fp = fsockopen('example.com', 80);
    
    $vars = array(
        'hello' => 'world'
    );
    $content = http_build_query($vars);
    
    fwrite($fp, "POST /reposter.php HTTP/1.1\r\n");
    fwrite($fp, "Host: example.com\r\n");
    fwrite($fp, "Content-Type: application/x-www-form-urlencoded\r\n");
    fwrite($fp, "Content-Length: ".strlen($content)."\r\n");
    fwrite($fp, "Connection: close\r\n");
    fwrite($fp, "\r\n");
    
    fwrite($fp, $content);
    

    【讨论】:

    • 这有多个问题。我将从主要问题开始。如果我在 PHP 退出之前不听结果,则连接在它能够完成之前关闭并且 POST 不成功。解决方案:在调用完 fwrite 之后做任何需要做的事情,然后在退出 PHP 之前监听结果。其他问题是 1) 这不安全。这应该通过 TLS 连接,并且 2)您需要在写入网络时检查 fwrite 的返回值。请参阅php.net/manual/en/function.fwrite.php 处的 fwrite_stream 示例
    【解决方案6】:

    Hookah 旨在解决您的问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-10-28
      • 2015-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-07-19
      • 1970-01-01
      相关资源
      最近更新 更多