2008-10-03 1 views
11

HttpRequestPool класс предоставляет решение. Большое спасибо тем, кто это указал.Параллельные запросы HTTP в PHP с использованием PECL HTTP классов [Ответ: HttpRequestPool класс]

Краткий учебник можно найти по адресу: http://www.phptutorial.info/?HttpRequestPool-construct


Проблема

Я хотел бы, чтобы одновременно/параллельно/одновременных запросов HTTP в PHP. Я хотел бы избежать последовательных запросов:

  • набор запросов займет слишком много времени; Чем больше запросов, чем дольше
  • таймаут одного запроса на полпути через набор может вызвать последующие запросы не быть (если сценарий имеет ограничение по времени выполнения)

мне удалось найти детали для изготовления simultaneuos [sic] HTTP requests in PHP with cURL , однако я бы хотел явно использовать PHP HTTP functions, если это вообще возможно.

В частности, мне нужно отправлять данные POST одновременно с набором URL-адресов. URL-адреса, на которые распространяются данные, находятся вне моего контроля; они настроены пользователем.

Я не возражаю, если мне нужно дождаться завершения всех запросов до того, как ответы будут обработаны. Если я устанавливаю тайм-аут 30 секунд на каждый запрос, и запросы выполняются одновременно, я знаю, что я должен ждать максимум 30 секунд (возможно, немного больше) для всех запросов.

Я не могу найти подробностей о том, как это может быть достигнуто. Тем не менее, я недавно заметил упоминание в руководстве PHP о том, что PHP5 + может обрабатывать одновременные HTTP-запросы - я намеревался записать его в это время, забыл и не могу найти его снова.

Single Пример запроса (работает отлично)

<?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: Я хотел бы придерживаться функций HTTP PECL как:

  • они предлагают приятный интерфейс ООП
  • они широко используются в применении в вопросе и придерживаться то, что уже используется, должно быть полезно с точки зрения обслуживания.
  • Обычно мне приходится писать меньше строк кода, чтобы сделать HTTP-запрос с использованием функций PECL HTTP по сравнению с использованием cURL. меньшее количество строк кода также должно быть полезно с точки зрения обслуживания

Разъяснения 2: Я понимаю, что функции HTTP в PHP не встроены в системе и, возможно, я сформулированные вещи неправильно там, что я поправлю. Я не беспокоюсь о том, что людям приходится устанавливать дополнительные вещи - это не приложение, которое должно быть распространено, это веб-приложение с сервером для себя.

Уточнение 3: Я был бы совершенно счастлив, если бы кто-то авторитетно заявил, что PECL HTTP не может этого сделать.

ответ

10

Я уверен, что HttpRequestPool - это то, что вы ищете.

Чтобы разработать немного, вы можете использовать forking для достижения того, что вы ищете, но это кажется излишне сложным и не очень полезным в контексте HTML.В то время как я не проверял, этот код должен быть его:

 
// let $requests be an array of requests to send 
$pool = new HttpRequestPool(); 
foreach ($requests as $request) { 
    $pool->attach($request); 
} 
$pool->send(); 
foreach ($pool as $request) { 
    // do stuff 
} 
-1

Вы можете использовать pcntl_fork(), чтобы создать отдельный процесс для каждого запроса, а затем ждать их до конца:

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

Есть ли какой-либо причине вы не хотите использовать Curl? Функции curl_multi_ * позволят одновременно выполнять несколько запросов.

+0

Это очень ресурсоемкий. Каждый php-процесс использует как минимум 20 МБ. – Gustav 2013-06-07 10:31:58

+0

Да, это пятилетний ответ. – bobwienholt 2013-06-07 13:35:49

0

HTTP-функции PHP aren't built in, либо - это расширение PECL. Если вы беспокоитесь о том, что людям приходится устанавливать дополнительные материалы, у обоих решений будет одна и та же проблема - и cURL, скорее всего, будет установлен, как я полагаю, поскольку он приходит по умолчанию с каждым веб-хостом, на котором я когда-либо был.

2

Вы попробовали HttpRequestPool (это часть Http)? Похоже, что он объединит объекты запроса и обработает их. Я знаю, что где-то я читал, что Http будет поддерживать одновременные запросы и кроме пул Я тоже ничего не могу найти.

2

Мне некогда приходилось решать аналогичную проблему: выполнение нескольких запросов без накопления времени отклика.

Решение получило функцию пользовательской сборки, которая использовала неблокирующие sockets. Это работает примерно так:

$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. 

Это гораздо быстрее, так как thunked Reponses выбираются в полупараллельное так socket_read не ждать ответа, но возвращается, если сокет-буфер не заполнен.

Вы можете обернуть это в соответствующие интерфейсы ООП. Вам будет нужно создать строку HTTP-запроса самостоятельно и обработать ответ сервера, конечно.

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) { ... }