11

HttpRequestPool类提供了一个解决方案 。非常感谢那些指出这一点的人。

可以在以下位置找到一个简短的教程:http ://www.phptutorial.info/?HttpRequestPool-construct


问题

我想在 PHP 中发出并发/并行/同时的 HTTP 请求。我想避免连续的请求:

  • 一组请求需要很长时间才能完成;请求越多时间越长
  • 一个请求在一组中途超时可能会导致以后的请求无法发出(如果脚本有执行时间限制)

我设法找到了使用 cURL 在 PHP 中同时发出 [原文如此] HTTP 请求的详细信息,但是如果可能的话,我想明确地使用 PHP 的HTTP 函数

具体来说,我需要将数据同时发布到一组 URL。发布数据的 URL 不在我的控制范围内;它们是用户设置的。

我不介意是否需要等待所有请求完成才能处理响应。如果我将每个请求的超时时间设置为 30 秒并且同时发出请求,我知道我必须等待最多 30 秒(可能更多)才能完成所有请求。

我找不到有关如何实现这一点的详细信息。但是,我最近确实注意到 PHP 手册中提到了 PHP5+ 能够处理并发 HTTP 请求 - 我当时打算记下它,忘记了,再也找不到了。

单个请求示例(工作正常)

<?php
$request_1 = new HttpRequest($url_1, HTTP_METH_POST);
$request_1->setRawPostData($dataSet_1);
$request_1->send();
?>

并发请求示例(不完整,清楚)

<?php
$request_1 = new HttpRequest($url_1, HTTP_METH_POST);
$request_1->setRawPostData($dataSet_1);

$request_2 = new HttpRequest($url_2, HTTP_METH_POST);
$request_2->setRawPostData($dataSet_2);

// ...

$request_N = new HttpRequest($url_N, HTTP_METH_POST);
$request_N->setRawPostData($dataSet_N);

// Do something to send() all requests at the same time
?>

任何想法将不胜感激!

澄清1:我想坚持PECL HTTP功能:

  • 他们提供了一个不错的 OOP 界面
  • 它们在有问题的应用程序中被广泛使用,并且从维护的角度来看,坚持已经使用的应该是有益的
  • 与使用 cURL 相比,我通常必须编写更少的代码行来使用 PECL HTTP 函数发出 HTTP 请求 - 从维护的角度来看,更少的代码行也应该是有益的

澄清 2:我意识到 PHP 的 HTTP 函数不是内置的,也许我在那里用词错误,我会更正。我不担心人们必须安装额外的东西——这不是一个要分发的应用程序,它是一个带有服务器的网络应用程序。

澄清 3:如果有人权威地声明 PECL HTTP 不能做到这一点,我会非常高兴。

4

6 回答 6

10

我很确定HttpRequestPool是您正在寻找的。

稍微详细一点,您可以使用分叉来实现您正在寻找的东西,但这似乎不必要地复杂并且在 HTML 上下文中不是很有用。虽然我还没有测试,这段代码应该是它:

// 让 $requests 是要发送的请求数组
$pool = 新的 HttpRequestPool();
foreach ($requests as $request) {
  $pool->attach($request);
}
$池->发送();
foreach ($pool as $request) {
  // 做东西
}
于 2008-10-12T22:53:38.477 回答
2

您是否尝试过HttpRequestPool(它是 Http 的一部分)?看起来它会汇集请求对象并处理它们。我知道我在某处读到 Http 会支持同时请求,除了之外我也找不到任何东西。

于 2008-10-10T10:37:42.687 回答
2

我曾经不得不解决类似的问题:在不累积响应时间的情况下执行多个请求。

该解决方案最终成为使用非阻塞套接字的自定义构建功能。它的工作原理是这样的:

$request_list = array(
  # address => http request string
  #
   '127.0.0.1' => "HTTP/1.1  GET /index.html\nServer: website.com\n\n",
   '192.169.2.3' => "HTTP/1.1 POST /form.dat\nForm-data: ...",
  );

foreach($request_list as $addr => $http_request) {
    # first, create a socket and fire request to every host
    $socklist[$addr] = socket_create();
    socket_set_nonblock($socklist[$addr]); # Make operation asynchronious

    if (! socket_connect($socklist[$addr], $addr, 80))
        trigger_error("Cannot connect to remote address");

    # the http header is send to this host
    socket_send($socklist[$addr], $http_request, strlen($http_request), MSG_EOF);
}

$results = array();

foreach(array_keys($socklist) as $host_ip) {
    # Now loop and read every socket until it is exhausted
    $str = socket_read($socklist[$host_ip], 512, PHP_NORMAL_READ);
    if ($str != "") 
        # add to previous string
        $result[$host_ip] .= $str;
    else
        # Done reading this socket, close it
        socket_close($socklist[$host_ip]);
}
# $results now contains an array with the full response (including http-headers)
# of every connected host.

由于 socket_read 不等待响应,而是在套接字缓冲区尚未满时返回,因此它以半并行方式获取 thunked 响应,因此速度要快得多。

您可以将其包装在适当的 OOP 接口中。您需要自己创建 HTTP 请求字符串,当然还要处理服务器响应。

于 2008-10-12T18:16:02.903 回答
1

最近,一位朋友向我指出了 CurlObjects ( http://trac.curlobjects.com/trac ),我发现它对使用 curl_multi 非常有用。

$curlbase = new CurlBase; $curlbase->defaultOptions[ CURLOPT_TIMEOUT ] = 30; $curlbase->add( new HttpPost($url, array('name'=> 'value', 'a' => 'b'))); $curlbase->add( new HttpPost($url2, array('name'=> 'value', 'a' => 'b'))); $curlbase->add( new HttpPost($url3, array('name'=> 'value', 'a' => 'b'))); $curlbase->perform();

foreach($curlbase->requests as $request) { ... }

于 2009-02-08T21:20:34.263 回答
0

PHP 的 HTTP 函数也不是内置的- 它们是 PECL 扩展。如果您担心人们必须安装额外的东西,那么两种解决方案都会遇到同样的问题 - 我想 cURL 更有可能被安装,因为它是我曾经使用过的每个网络主机的默认设置。

于 2008-10-03T21:54:12.123 回答
-1

您可以使用 pcntl_fork() 为每个请求创建一个单独的进程,然后等待它们结束:

http://www.php.net/manual/en/function.pcntl-fork.php

你有什么不想使用 cURL 的理由吗?curl_multi_* 函数将允许同时处理多个请求。

于 2008-10-03T21:39:14.617 回答