2008-10-03 28 views
11

La clase HttpRequestPool proporciona una solución. Muchas gracias a los que señalaron esto.paralelas peticiones HTTP en PHP utilizando PECL clases HTTP [Respuesta: HttpRequestPool clase]

Un breve tutorial se puede encontrar en: http://www.phptutorial.info/?HttpRequestPool-construct


Problema

me gustaría hacer concurrentes/paralelos/solicitudes HTTP simultáneas en PHP. Me gustaría evitar las solicitudes consecutivas como:

  • un conjunto de solicitudes tomará demasiado tiempo para completar; los más solicitudes cuanto más tiempo
  • el tiempo de espera de una solicitud a medio camino a través de un conjunto puede causar que no se pueden hacer solicitudes posteriores (si un guión tiene un límite de tiempo de ejecución)

he logrado encontrar detalles para hacer simultaneuos [sic] HTTP requests in PHP with cURL Sin embargo, me gustaría utilizar explícitamente el HTTP functions de PHP, si es posible.

Específicamente, necesito POSTAR datos simultáneamente a un conjunto de URL. Las URL a las que se envían los datos están fuera de mi control; están establecidos por el usuario.

No me importa si tengo que esperar a que finalicen todas las solicitudes para poder procesar las respuestas. Si establezco un tiempo de espera de 30 segundos en cada solicitud y las solicitudes se realizan al mismo tiempo, sé que debo esperar un máximo de 30 segundos (quizás un poco más) para que se completen todas las solicitudes.

No puedo encontrar detalles de cómo se puede lograr esto. Sin embargo, hace poco noté una mención en el manual de PHP de PHP5 + que me permitía manejar solicitudes HTTP simultáneas. Tenía la intención de anotarlo en ese momento, olvidarlo y no volver a encontrarlo.

ejemplo de solicitud única (funciona bien)

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

ejemplo de solicitudes simultáneas (incompleta, claro)

<?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 
?> 

serían más apreciados Cualquier pensamiento!

Aclaración 1: Me gustaría que se adhieren a las funciones HTTP PECL como:

  • que ofrecen una interfaz de programación orientada a objetos agradable
  • se usan ampliamente en la aplicación en cuestión y ajustarse a lo que ya está en uso debería ser beneficioso desde el punto de vista de mantenimiento
  • Por lo general, tengo que escribir menos líneas de código para hacer una solicitud HTTP usando las funciones HTTP PECL en comparación con el uso de cURL: menos líneas de código también deberían ser beneficiosas desde una perspectiva de mantenimiento

Aclaración 2: Me dan cuenta de las funciones de PHP HTTP no se construyen en y tal vez redactadas las cosas erróneamente allí, lo que voy a corregir. No me preocupa que las personas tengan que instalar cosas adicionales; esta no es una aplicación que se distribuirá, es una aplicación web con un servidor para sí misma.

aclaración 3: Estaría muy feliz si alguien autorizadamente indica que el HTTP PECL no puede hacer esto.

Respuesta

10

Estoy bastante seguro de que HttpRequestPool es lo que estás buscando.

Para elaborar un poco, puede usar bifurcación para lograr lo que está buscando, pero eso parece innecesariamente complejo y poco útil en un contexto HTML.Aunque no he probado, este código debería ser éste:

 
// 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 
} 
+0

No se encontró en 2017 ... – kiltek

-1

Usted podría utilizar pcntl_fork() para crear un proceso separado para cada solicitud, a continuación, esperar a que se terminan:

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

¿Hay alguna razón usted no desea utilizar cURL? Las funciones curl_multi_ * permitirían múltiples solicitudes al mismo tiempo.

+0

Esto consume muchos recursos. Cada proceso php usa al menos 20 MB. – Gustav

+0

Sí, y esta es una respuesta de cinco años. – bobwienholt

0

Las funciones HTTP de PHP aren't built in, bien - son una extensión PECL. Si su preocupación es que la gente tenga que instalar cosas adicionales, ambas soluciones tendrán el mismo problema, y ​​es más probable que se instale cURL, supongo, ya que viene con todos los servidores web en los que he estado.

2

¿Has probado HttpRequestPool (es parte de Http)? Parece que agruparía los objetos de solicitud y los trabajaría. Sé que leí en alguna parte que Http admitiría solicitudes simultáneas y, aparte de grupo, tampoco puedo encontrar nada.

2

Una vez tuve que resolver un problema similar: hacer varias solicitudes sin acumular los tiempos de respuesta.

La solución terminó siendo una función de creación personalizada que utilizaba sockets sin bloqueo. funciona algo como esto:

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

Es mucho más rápido ya que thunked reponses se recuperan en semi-paralelo desde socket_read no espera a la respuesta, sino que vuelve si el socket-buffer no está lleno todavía.

Puede envolver esto en las interfaces OOP apropiadas. Usted necesitará crear usted mismo la cadena de solicitud HTTP y procesar la respuesta del servidor, por supuesto.

1

Un amigo me señaló a CurlObjects (http://trac.curlobjects.com/trac) Recientemente, que me pareció bastante útil para usar 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) { ... }