Domanda


La classe HttpRequestPool fornisce una soluzione. Mille grazie a coloro che lo hanno sottolineato.

Un breve tutorial è disponibile all'indirizzo: http: // www. phptutorial.info/?HttpRequestPool-construct


problema

Vorrei fare richieste HTTP simultanee / parallele / simultanee in PHP. Vorrei evitare richieste consecutive come:

  • un insieme di richieste richiederà troppo tempo per essere completato; più richieste più lungo
  • il timeout di una richiesta a metà di un set può causare la mancata presentazione di richieste successive (se uno script ha un limite di tempo di esecuzione)

Sono riuscito a trovare i dettagli per rendere simultaneuos [sic ] Richieste HTTP in PHP con cURL , tuttavia mi piacerebbe utilizzare esplicitamente di PHP Funzioni HTTP se possibile,

In particolare, devo inviare i dati contemporaneamente a una serie di URL. Gli URL in cui vengono pubblicati i dati sono al di fuori del mio controllo; sono impostati dall'utente.

Non mi dispiace se devo attendere il completamento di tutte le richieste prima che le risposte possano essere elaborate. Se imposto un timeout di 30 secondi per ogni richiesta e le richieste vengono fatte contemporaneamente, so che devo attendere un massimo di 30 secondi (forse un po 'di più) per completare tutte le richieste.

Non riesco a trovare dettagli su come raggiungere questo obiettivo. Tuttavia, recentemente ho notato una menzione nel manuale PHP di PHP5 + in grado di gestire richieste HTTP simultanee - avevo intenzione di prenderne nota al momento, ho dimenticato e non riesco a trovarlo di nuovo.

Esempio di singola richiesta (funziona correttamente)

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

Esempio di richiesta simultanea (incompleta, chiaramente)

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

Qualsiasi pensiero sarebbe molto apprezzato!

Chiarimento 1 : vorrei attenermi alle funzioni HTTP PECL come:

  • offrono una bella interfaccia OOP
  • sono ampiamente utilizzati nell'applicazione in questione e attenersi a ciò che è già in uso dovrebbe essere utile dal punto di vista della manutenzione
  • In genere devo scrivere meno righe di codice per effettuare una richiesta HTTP utilizzando le funzioni HTTP PECL rispetto all'utilizzo di cURL: anche meno righe di codice dovrebbero essere utili dal punto di vista della manutenzione

Chiarimento 2 : mi rendo conto che le funzioni HTTP di PHP non sono integrate e forse ho scritto cose errate lì, che correggerò. Non ho dubbi sul fatto che le persone debbano installare roba extra - questa non è un'applicazione che deve essere distribuita, è un'app Web con un server a sé.

Chiarimento 3 : sarei perfettamente felice se qualcuno affermasse in modo autorevole che l'HTTP PECL non può farlo.

È stato utile?

Soluzione

Sono abbastanza sicuro che HttpRequestPool è quello che stai cercando per.

Per elaborare un po ', puoi usare il fork per ottenere ciò che stai cercando, ma questo sembra inutilmente complesso e non molto utile in un contesto HTML. Anche se non ho ancora testato, questo codice dovrebbe essere:

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

Altri suggerimenti

Hai provato HttpRequestPool (fa parte di Http)? Sembra che raggrupperebbe gli oggetti richiesta e li lavorerebbe. So di aver letto da qualche parte che Http supporterebbe le richieste simultanee e a parte il pool non riesco a trovare nulla.

Una volta ho dovuto risolvere un problema simile: fare più richieste senza accumulare i tempi di risposta.

La soluzione è risultata essere una funzione di creazione personalizzata che utilizzava socket non bloccanti. Funziona in questo modo:

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

È molto più veloce poiché le risposte thunk vengono recuperate in semi-parallelo poiché socket_read non aspetta la risposta ma ritorna se il buffer del socket non è ancora pieno.

Puoi avvolgerlo nelle interfacce OOP appropriate. dovrai creare tu stesso la stringa di richiesta HTTP ed ovviamente elaborare la risposta del server.

Un amico mi ha indicato CurlObjects ( http://trac.curlobjects.com/trac ) recentemente, che ho trovato abbastanza utile per l'uso di curl_multi.

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

foreach ($ curlbase- > richieste come $ request) { ... }

Le funzioni HTTP di PHP non sono integrate , neanche - sono un'estensione PECL. Se la tua preoccupazione è che le persone debbano installare roba extra, entrambe le soluzioni avranno lo stesso problema - e cURL ha maggiori probabilità di essere installato, immagino, dato che arriva di default con ogni host web in cui sia mai stato.

Potresti usare pcntl_fork () per creare un processo separato per ogni richiesta, quindi attendere che finiscano:

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

C'è qualche motivo per cui non vuoi usare cURL? Le funzioni curl_multi_ * consentirebbero più richieste contemporaneamente.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top