Cómo hacer muchas peticiones HTTP simultáneas en PHP

·

Uno de los problemas que habitualmente nos pueden frenar la carga de un sitio es si leemos mucha información de varios sitios de forma simultánea, como podría ser la lectura de varios feeds. Y es que habitualmente se usa la función file_get_contents() que tiene una cosa: es síncrona, es decir, hay que ejecutarla, esperar a que finalice, y volver a ejecutarla… pero ¿por qué esperar a qué acabe de leer para hacer otra llamada?

Para hacerlo podemos utilizar las funciones curl_multi_* que básicamente permiten hacer muchas llamadas cURL en muy poco tiempo. No es del todo asíncrono y en paralelo, pero casi casi se podría considerar como una opción.

El tiempo total de estas peticiones será la de la más lenta de todas, de forma que si tenemos algo como esto:

  • URL 1: 2,3 segundos
  • URL 2: 0,3 segundos
  • URL 3: 1,4 segundos
  • URL 4: 1,8 segundos
  • URL 5: 3,0 segundos

de la forma normal tardaríamos 8,8 segundos 8que es la suma de todos, aunque habría que sumarle los tiempos de conexión y desconexión), y de la forma que propongo se tardaría un poco más de 3,0 segundos, que es el tiempo de la más lenta de todas.

¿Cómo hacer esto?

<?php
function PeticionMultiple($urls, $opciones = array()) {
$curly = array();
$resultado = array();
$pm = curl_multi_init();
foreach ($urls as $id => $d) {
$curly[$id] = curl_init();
if(is_array($d) && !empty($d['url'])) {
$url = $d['url'];
} else {
$url = $d;
}
curl_setopt($curly[$id], CURLOPT_URL, $url);
curl_setopt($curly[$id], CURLOPT_HEADER, 0);
curl_setopt($curly[$id], CURLOPT_RETURNTRANSFER, 1);
if (!empty($d['post'])) {
curl_setopt($curly[$id], CURLOPT_POST, 1);
curl_setopt($curly[$id], CURLOPT_POSTFIELDS, $d['post']);
}
if (!empty($opciones)) {
curl_setopt_array($curly[$id], $opciones);
}
curl_multi_add_handle($pm, $curly[$id]);
}
$ejecutando = null;
do {
curl_multi_exec($pm, $ejecutando);
} while($ejecutando > 0);
foreach($curly as $id => $c) {
$resultado[$id] = curl_multi_getcontent($c);
curl_multi_remove_handle($pm, $c);
}
curl_multi_close($pm);
return $resultado;
}
?>

Y el código de invocación:

<?php
$urls = array(
'http://javiercasares.com/feed/atom/',
'http://www.ethek.com/feed/atom/',
'http://www.tumanitas.com/feed/'
);
$r = PeticionMultiple($urls);
print_r($r);
?>

Con esto, en principio, conseguiríamos múltiples peticiones para leer feeds de muchos sitios lo más rápido posible…

Relacionado: interesante la función EpicCurl del código EpiCode.

Comments

4 respuestas a «Cómo hacer muchas peticiones HTTP simultáneas en PHP»

  1. Avatar de osek

    Hola!, he probado con esto, pero no me resulta. Me tira error en la línea 8 del código. Me podrías ayudar?

    Saludos,

  2. Avatar de Yo

    Le falta un punto y coma al final de la línea de asiganación de la URL aqui está incluida.
    if(is_array($d) && !empty($d[‘url’])) {
    $url = $d[‘url’]; //Aqui falta el punto y coma.
    } else {
    $url = $d;
    }

Responder a Yo Cancelar la respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *