Web Crawler distribuido usando AjMessages

Published on Author lopez2 Comments

En Enero pasado, actualicé mi proyecto AjMessages para que soporte comunicación usando DSS/CCR y Windows Communication Foundation. AjMessage puede ejecutarse de forma distribuida, enviando mensajes desde un nodo lógico a otro. Los nodos lógicos pueden albergarse en una o más máquinas física. Más información sobre AjMessages en:

AjMessages- a message processor
Distributed Applications with AjMessages using DSS/CCR
Aplicaciones Distribuidas con AjMessages usando DSS/CCR
AjMessages- hacia un procesador de mensajes

Pueden descargar el código fuente desde

http://www.codeplex.com/ajmessages

Tenía la idea de escribir un procesador de mensajes distribuidos. Hace unos años, escribí mi primer intento, llamado AjServer

Hacia el AjServer

Luego, encontré al proyecto Fabriq, estudiando sus ideas e implementación. En ese proyecto, hay manejadores (handlers) lógicos de mensajes, que pueden instalarse de modo distribuido, de forma transparente, cambiando la información de configuración:

En el 2007, escribí la primera versión de AjMessages, como prueba de concepto: pude reproducir bastante de las ideas de Fabriq, y a la vez, elevar el nivel de abstracción de algunos puntos, para conseguir mayor flexibilidad. Fabriq estaba más orientado a SOA. AjMessages se orienta a mensajes arbitrarios, que coordinados, pueden funcionar en una aplicación en grilla.

La solución actual de AjMessages es:

Hay un proyecto núcleo, y dos proyectos de transporte: uno para soporte de WCF, y otro que se basa en DSS/CCR (tecnologías de Microsoft Robotics). Si no tienen DSS/CCR instalado, pueden remover los proyectos que lo referencia. El núcleo de AjMessages está lib de dependencias de esas tecnologías.

AjMessages.SampleApp contiene un simple manejador de mensajes: un decrementador de enteros, que toma un mensaje de entrada, con un contenido entero, lo decrementa, y produce un nuevo mensaje.

En cambio, AjMessages.WebCrawler implementa el mensaje y manejadores de mensajes para armar un web crawler distribuido. Pueden ejecutarlo desde una sola máquina, o en varias.

Cara AjMessages tiene:

Body: un contenido arbitrario
Headers: información adicional, por clave/valor.
Action: describe el destino del mensaje, usando un patrón Aplicación/Nodo/Acción

(más detalle en AjMessages- hacia un procesador de mensajes)

Exploremos el ejemplo de web crawler. Esta aplicación está compuesta de nodos, que pueden ser orquestado para visitar una página web, tomar de esa página todos los enlaces relacionados, y volver a tomar esas páginas. Para que no sea un proceso infinito, la visita de páginas se limita al sitio inicial, y hasta un nivel de profundidad. La aplicación puede ser descripta lógicamente con este diagrama:

El primer mensaje se envía al nodo Controller, a su acción Dispatch. Ese primer mensaje contiene la dirección de la página a visitar. El mensaje es enriquecido, y pasado al nodo Controller, acción Resolve. Este nodo está a cargo de mantener la lista de páginas ya visitadas, y de controlar la profundidad de exploración. Si el enlace recibido es aprobado, entonces el mensaje es enviado al nodo Downloader, acción Download. El contenido de la página es recuperado, agregado al mensaje, y reenviado al nodo Harvester, a su acción Harvest. Esta acción analiza el contenido de la página, y emite varios mensajes, uno por cada enlace encontrado. El receptor de esos nuevos enlaces es el nodo Resolver, en su acción Resolve. Así, el proceso continua hasta visitar todas las páginas (con un límite en la profundidad a explorar).

Esta aplicación se puede describir en un archivo de configuración XML, como por ejemplo:

<?xml version="1.0" encoding="utf-8" ?> <AjMessages> <Application Name="WebCrawler"> <Node Name="Dispatcher"> <Handler Name="DispatcherHandler" Type="AjMessages.WebCrawler.Handlers.Dispatcher, AjMessages.WebCrawler"/> <Action Name="Dispatch" Handler="DispatcherHandler"/> </Node> <Node Name="Harvester"> <Handler Name="HarvesterHandler" Type="AjMessages.WebCrawler.Handlers.Harvester, AjMessages.WebCrawler"/> <Action Name="Harvest" Handler="HarvesterHandler"/> </Node> <Node Name="Downloader"> <Handler Name="DownloaderHandler" Type="AjMessages.WebCrawler.Handlers.Downloader, AjMessages.WebCrawler"/> <Action Name="Download" Handler="DownloaderHandler"/> </Node> <Node Name="Controller"> <Handler Name="ResolverHandler" Type="AjMessages.WebCrawler.Handlers.Resolver, AjMessages.WebCrawler"/> <Action Name="Resolve" Handler="ResolverHandler"/> </Node> </Application> </AjMessages>

Un aplicación, entonces, está compuesta de nodos lógicos. Cada nodo puede ser visto como una clase lógica. Cada nodo puede manejar acciones, que son los puntos destinos de los mensajes. Una acción puede estar compuesta de uno o varios pasos. Este es el punto de extensibilidad de la aplicación: deben proveer los pasos, el manejador de mensaje, y escribir el archivo de configuración que orquestre el procesamiento de los mensajes.

Pero una cosa es la aplicación, y otra es su distribución en máquinas físicas. Pueden tener dos hosts, e instalar diferentes nodes en cada uno:

En este diagrama, el Dispatcher y el Resolver están en un hosts, mientras que el Downloader y el Harvester están en otro. Pero Uds. pueden poner Harverstes en cada hosts, o en veinte máquinas. Queda en Uds. cómo distribuir la carga del trabajo. Cuando un mensaje es enviado a un destino (Aplicación/Nodo/Acción),  AjMessage lo reenvía a un host apropiado, que contenga un nodo capaz de procesar el mensaje.

La distribución de nodos lógicos en un host físico se define via configuración, por ejemplo:

<?xml version="1.0" encoding="utf-8" ?> <AjMessages> <Host Name="Server1" Address="http://localhost:50002/AjMessages" Activate="true"> <Application Name="AjMessages"> <Node Name="Administration"/> </Application> <Application Name="WebCrawler"> <Node Name="Controller"/> <Node Name="Dispatcher"/> <Node Name="Harvester"/> <Node Name="Downloader"/> </Application> </Host> <Host Name="Server2" Address="http://localhost:50003/AjMessages"> <Application Name="AjMessages"> <Node Name="Administration"/> </Application> <Application Name="WebCrawler"> <Node Name="Dispatcher"/> <Node Name="Harvester"/> <Node Name="Downloader"/> </Application> </Host> </AjMessages>

Ejecutando el ejemplo Web Crawler

Pueden probar el programa, lanzando dos hosts, en la misma máquina. Hay que ejecutar el programa de consola AjMessage.Console. Al comenzar esta aplicación, podemos ingresar el comando

fork

Este comando lanza un segundo host. Ahora, podemos configurar los dos hosts. En el primero, ingresamos:

load ConfigurationServer1.xml

Este archivo carga la aplicación AjMessage inicial (es una aplicación más dentro de “la grilla”), y define un endpoint WCF para escuchar mensajes de otros posibles hosts. Ahora, en la misma consola, ingresamos:

load ConfigurationWebCrawler.xml

Este comando carga la definición de la aplicación Web Crawler, con sus nodos lógicos (no hay información de deploy todavía). El tercer comando, define la distribución física de hosts:

load ConfigurationWebCrawlerNode1.xml

Ahora, volvamos a la segunda consola. Ahí, ingresamos los comandos:

load ConfigurationServer2.xml
load ConfigurationWebCrawler.xml
load ConfigurationWebCrawlerNode2.xml

Estamos listos para lanzar el primer web crawling. Vamos a la primera consola, e ingresamos:

send WebCrawler/Dispatcher/Dispatch http://ajlopez.zoomblog.com

El programa comienza a trabajar, en AMBAS consolas. Una típica salida de la primera consola:

Próximos pasos

Debería arreglar algunos problemas en el transporte DSS/CCR (actualmente, puede ejecutar una aplicación simple como el decrementador de enteros, pero no con el web crawler). Dos puntos para implementar:

– Configuración remota de nodos
– Distribución de los manejadores de mensajes (sus .dlls) a los nodos remotos
– Una configuración para todos los nodos (ahora, cada nodo es configurado separadamente)

Comencé un experimento con un proceso más abstracto de mensajes, que quisiera que pudiera implementar casos de uso como:

– Un simple hello world
– El ejemplo de decrementar enteros
– Web crawler distribuido
– Una especie de Enterprise Service Bus

Pueden ver mis primeros pasos en:

http://code.google.com/p/ajcodekatas/source/browse#svn/trunk/AjProcessor

Todavía en desarrollo.

Nos leemos!

Angel “Java” Lopez
http://www.ajlopez.com/
http://twitter.com/ajlopez

Leave a Reply

Your email address will not be published. Required fields are marked *