Como acceder a múltiples servicios web en paralelo con PHP
Veamos el caso de una aplicación Web donde se realizan búsquedas en base a cierta información ingresada por el usuario, y para generar los resultados, el sistema debe consultar varios servicios web, los cuales tardan varios segundos en responder. Habría que buscar una forma de minimizar el tiempo de búsqueda para que al cliente le lleguen los resultados antes que la muerte.
La solución que propongo fue aplicada en un sistema de búsqueda y reserva de vuelos y hoteles.
Se pueden utilizar varias técnicas, yo tuve en cuenta las siguientes:
- Acceder a los web services en forma concurrente utilizando CURL: Se podría buscar y generar la página de resultados directamente, o hacerlo mediante AJAX, lo cual nos permitiría hacer un polling e ir obteniendo resultados parciales.
Sería la solución mas elegante, pero hay que tener en cuenta que desgraciadamente no todos los web services son de tipo REST y algunos usan SOAP, por lo tanto se hace dificil implementarlo usando esta librería porque habría que generar el XML e interpretar la respuesta manualmente. Mucho trabajo a mi parecer. - Implementar threads: Quizás piensen en el suicidio antes de tener en cuenta esta opción.
- Buscar la solución en el lado del cliente y enviar una petición AJAX por cada web service: Aún así tenemos el problema de los límites de conección por host que imponen algunos navegadores como IE 6 y 7.
En principio opté por la última opción, pero me vi forzado a descartar el uso de AJAX debido a que algunos browsers imponen un límite de 2 conecciones concurrentes por host y yo necesito consultar 6 servicios web. Para evitar este límite tenemos que engañar al navegador creando al menos 3 subdominios, los cuales nos permitiría realizar 6 peticiones en paralelo, 2 por cada uno.
Quizás la solución no es muy elegante pero es muy usada para agilizar la descarga de los distintos componentes de la página. Tal es el caso de Google Maps, que utiliza subdominios mt0.google.com, mt1.google.com, mt2.google.com, etc.
Si bien no podemos enviar una petición a otro subdominio usando AJAX (hasta el momento), podemos inyectar un script en el documento y cumpliría la misma función, siempre y cuando la respuesta sea en formato JSON. Aca va un ejemplo usando jQuery:
$(function() {
var webServices = [1,2,3,4,5,6]; // id's de los webservices
var count = 1, host;
for (var i = 0; i < webServices.length; i++) {
// generamos un host
host = 'http://ws' + count + '.' + location.host + '/search?ws=' + i;
if ((i+1)%2 == 0) count++;
// enviamos el request, jQuery inyecta el script en el documento al detectar otro dominio
$.getJSON(host, function(json) {
// actualizamos los resultados...
$('#results').html(json.results);
});
}
});
Aunque en el título menciono a PHP, mas bien nos limita en vez de darnos una solución práctica.
