Question

La classe HttpRequestPool fournit une solution. Un grand merci à ceux qui l'ont signalé.

Vous trouverez un bref didacticiel à l'adresse: http: // www. phptutorial.info/?HttpRequestPool-construct

Problème

J'aimerais faire des requêtes HTTP simultanées / parallèles / simultanées en PHP. J'aimerais éviter les requêtes consécutives en tant que:

  • un ensemble de demandes prendra trop de temps; plus il y a de demandes, plus longtemps
  • le délai d'expiration d'une requête au milieu d'un ensemble peut empêcher la création de requêtes ultérieures (si un script a une durée limite d'exécution)

J'ai réussi à trouver les détails permettant de créer simultaneuos [sic ] Les requêtes HTTP en PHP avec cURL , mais j’aimerais utiliser explicitement le de PHP Fonctions HTTP si possible.

Plus précisément, j'ai besoin de poster des données simultanément sur un ensemble d'URL. Les URL sur lesquelles les données sont publiées sont hors de mon contrôle; ils sont définis par l'utilisateur.

Cela ne me dérange pas de devoir attendre que toutes les demandes soient terminées avant que les réponses ne puissent être traitées. Si je fixe un délai d'expiration de 30 secondes pour chaque demande et que les demandes sont effectuées simultanément, je sais que je dois attendre 30 secondes au maximum (peut-être un peu plus) pour que toutes les demandes soient terminées.

Je ne trouve aucun détail sur la manière dont cela pourrait être réalisé. Cependant, j'ai récemment remarqué une mention dans le manuel PHP de PHP5 + capable de gérer les requêtes HTTP simultanées. J'avais l'intention d'en prendre note à ce moment-là. J'ai oublié et je ne peux pas la retrouver.

Exemple de demande simple (fonctionne bien)

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

Exemple de demande simultanée (incomplet, clairement)

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

Toutes vos pensées seraient les bienvenues!

Clarification 1 : je voudrais m'en tenir aux fonctions HTTP de PECL en tant que:

  • ils offrent une belle interface POO
  • ils sont largement utilisés dans l'application en question et s'en tenir à ce qui est déjà utilisé devrait être avantageux du point de vue de la maintenance
  • Je dois généralement écrire moins de lignes de code pour effectuer une requête HTTP à l'aide des fonctions HTTP PECL par rapport à cURL. Moins de lignes de code devrait également être bénéfique du point de vue de la maintenance

Clarification 2 : je me rends compte que les fonctions HTTP de PHP ne sont pas intégrées et peut-être que j'ai mal formulé les choses, que je corrigerai. Je ne crains pas que des personnes installent des éléments supplémentaires: ce n'est pas une application à distribuer, c'est une application Web avec un serveur pour elle-même.

Clarification 3 : Je serais parfaitement heureux si quelqu'un affirmait avec autorité que le protocole HTTP PECL ne pouvait pas le faire.

Était-ce utile?

La solution

Je suis presque certain que HttpRequestPool pour.

Pour en dire un peu plus long, vous pouvez utiliser le forking pour obtenir ce que vous cherchez, mais cela semble inutilement complexe et peu utile dans un contexte HTML. Bien que je n'ai pas testé, ce code devrait être le suivant:

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

Autres conseils

Avez-vous essayé HttpRequestPool (fait partie de Http)? Il semblerait que les objets de requête soient regroupés et exploités. Je sais que j'ai lu quelque part que Http prend en charge les requêtes simultanées et en dehors du pool , je ne trouve rien non plus.

J'ai déjà eu à résoudre un problème similaire: faire plusieurs demandes sans cumuler les temps de réponse.

La solution a fini par être une fonction de construction personnalisée qui utilisait des sockets non bloquants. Cela fonctionne à peu près comme ceci:

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

C'est beaucoup plus rapide puisque les réponses répondues sont extraites en semi-parallèle car socket_read n'attend pas la réponse mais retourne si le tampon de socket n'est pas encore complet.

Vous pouvez envelopper cela dans les interfaces de POO appropriées. Vous devrez créer vous-même la chaîne de requête HTTP et bien sûr traiter la réponse du serveur.

Un ami m'a indiqué à CurlObjects ( http://trac.curlobjects.com/trac ). récemment, que j'ai trouvé assez utile pour utiliser curl_multi.

$ curlbase = new CurlBase; $ curlbase- > defaultOptions [CURLOPT_TIMEOUT] = 30; $ curlbase- > add (new HttpPost ($ url, array ('name' = > 'value', 'a' = 'g'; '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- > request as $ request) { ... }

Les fonctions HTTP de PHP ne sont pas intégrées à , soit: ils sont une extension PECL. Si vous êtes préoccupé par le fait que les utilisateurs doivent installer des éléments supplémentaires, les deux solutions auront le même problème - et cURL est plus susceptible d’être installé, je l’imagine, car il est livré par défaut avec chaque hôte Web sur lequel j’ai déjà travaillé.

Vous pouvez utiliser pcntl_fork () pour créer un processus distinct pour chaque demande, puis attendre la fin de celle-ci:

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

Y a-t-il une raison pour laquelle vous ne souhaitez pas utiliser cURL? Les fonctions curl_multi_ * autoriseraient plusieurs requêtes en même temps.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top