Archive for the '6148' Category

Introducción a AjProcessor (Parte 1)

Thursday, April 23rd, 2009

En marzo, estuve trabajando en el código de AjProcessor, parte de mi proyecto de Code Kata en Google:

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

La idea es la evolución de código experimental que hice con AjMessages y otros ejemplos. Quiero tener una aplicación, basada en el pasaje de mensajes, que pueda ejecutar en una grilla de máquinas heterogéneas. La aplicación podría ser dividida en pasos, y cada paso podría ejecutar en la misma máquina, para prueba local, o en distintas máquinas. El despliegue de la aplicación en distintas máquinas debería ser transparente a la escritura del código de la aplicación.

Alguno de esos objetivos fueron alcanzados con AjMessages, pero esta vez, quiero partir de una base más limpia, basada en las lecciones aprendidas en los anteriores intentos.

Primero, quiero pasar en limpio algunas ideas básicas, para explicar la motivación del código que está apareciendo en el proyecto. La idea básica es tener lo que llamo processors, procesadores, código que recibe un mensaje y lo procesa.

El mensaje tiene un payload, contenido, que puede ser un objeto arbitrario, un string, o cualquier otra cosa, y propiedades adicionales, en forma de pares clave/valor.

Otro ladrillo esencial en esta aplicación tipo lego, es el elemento que publica mensajes. Hay entonces un publisher:

El mensaje saliente puede ser recibido por cualquier otro código. El mismo mensaje puede ser procesado por más de otro Processor:

Es como el patrón publish/subscribe. Otro patrón a tomar en cuenta, es un componente tipo router. Dependiendo de algo del mensaje (propiedad, contenido), o del entorno (balanceo de carga), envía el mensaje a diferentes destinos.

Muchas veces, un componente implementará ambos roles, de de Message Processor y el de Message Publisher. Para facilitar la llamada a objetos .NET comunes, sería bueno tener un procesador que reciba un mensaje, toma una parte del mismo (por ejemplo, el contenido), y lo envía como parámetro a un método del objeto .NET. El valor de retorno podría ser tomado como contenido de un nuevo mensaje saliente.

Los componentes pueden ser dispuestos en cadena, implementando una especie de pipeline/tubería donde procesar un mensaje:

Una disposición más compleja sería recibir un mensaje, y reenviarlo a diferentes pipelines, según el contenido o propiedad del mensaje entrante. Y tomar los mensajes salientes de los pipelines, para reenviarlos al próximo paso.

(este concepto podría ser mapeado al concepto de Application en AjMessages, pero sin la idea de procesacimiento distribuido). Una idea más interesante es ejecutar una especie de ruteadores a pipelines, pero en varias máquinas

La infraestructura de AjProcessor estaría a cargo de la serialización, deserialización y ruteo de mensajes entre distintas máquinas anfitrionas. Podría enviar mensajes usando Windows Communication Foundation (WCF), o cualquier otra tecnología. La idea es tener un trasporte que se pueda agregar o definir, en configuración, sin afectar al funcionamiento de la aplicación.

Bien, todas estas son las ideas iniciales que forman el fundameto el proyecto. En un próximo espero explicar algo del código actual (apenas algunas interfaces, clases de implementación y tests).

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

Web Crawler distribuido usando AjMessages

Monday, March 9th, 2009

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

Seminario gratuito: Programación Paralela, Programación Distribuida, High Performance Computing

Monday, December 29th, 2008

Desde fines del 2006, estoy trabajando con programación distribuida, usando CCR/DSS, WCF y otras tecnologías, como Message Passing Interface. En estas últimas semanas, comencé a trabajar con High Performance Computing Windows HPC Server 2008.

Ahora, en Enero, daremos con Sebastián Renzi  (@SebaRenzi) un seminario gratuito en el Microsoft User Group:

SEMINARIO GRATUITO “Programación Paralela, Programación Distribuida, High Performance Computing”.
Thursday, January 15, 2009
Lugar: Auditorio del MUG, Rivadavia 1479 1º A, Ciudad de Buenos Aires.

Ahí está el abstract:

Hay aplicaciones que necesitan procesar gran cantidad de información, o que tienen requerimientos de velocidad exigente.
Exploraremos en la charla algunas tecnologías y estrategías que tenemos disponibles como:
– Programación Paralela: usando múltiples threads, TPL (Task Parallel Library).
– Programación Distribuida: enviando el trabajo a realizar a distintas máquinas, usando WCF o DSS/CCR
– High Performance Computing: ejecutando jobs, tasks, y programas

HPC Server 2008 es el producto de Microsoft que permite armar un cluster de máquinas, pudiendo llegar a tener cientos de nodos.
Es la tendencia actual en supercomputación.

Mostraremos ejemplos de código de cada uno.

Las vacantes son limitadas.

La idea es explorar algunas ideas de AjMessages, grid computing, Task Parallel Library, MPI, MPI.NET y programación HPC. También mostrar código andando, esperamos poder llevar un cluster virtualizado andando, para mostrarlo en la charla.

Nos leemos!

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

Aplicaciones distribuidas con AjMessages usando DSS/CCR

Friday, October 10th, 2008

Por ahora, es solo un proyecto en marcha. La aplicación de ejemplo es mínima. Pero es la evolución de mi trabajo anterior con AjMessages usando  Windows Communication Foundation:

AjMessages- a message processor
AjMessages- hacia un procesador de mensajes

El año pasado excribí ese ejemplo, y otro que usaba DSS/CCR. Solo el primero fue publicado, ahora, estuve revisando mi implementación con DSS/CCR, tecnologías que son la base de Microsoft Robotics. El código nuevo se puede bajar del repositorio de CodePlex en:

http://www.codeplex.com/ajmessages

Los ejemplos estan basados en ideas del proyecto Fabriq, ahora en nuevas tecnologías. En estos días, Arvindra Sehmi escribió sobre una nueva versión de Fabriq, llamada Fabriq4Dss, que está usando DSS/CCR como base. Preparó una presentación para la conferencia JAOO, lean:

JAOO 2008 Presentation

Espero que pronto aparezcan novedades sobre esa implementación y otras. Keep tuned!

La solución

Tiene tres proyectos:

El primero es la implementación del núcleo del sistema, que es independiente del transporte de los mensajes distribuidos:

El segundo proyecto contiene un ejemplo con un message handler que decrementa un entero. El tercer proyecto es un DSS Service Component que se usa para albergar el servidor de AjMessages en una máquina con un DSS Host:

 

Para una más detallada explicación de qué es una aplicación, mensaje, servidor, leer mis anteriores posts:

AjMessages- a message processor
AjMessages- hacia un procesador de mensajes

La aplicación

Un archivo de configuración XML define las aplicaciones a ejecutar. Una aplicación tiene:

  • Nodes: una colección de acciones a procesar (un nodo tiene varias acciones, podría ser análogo a clase/método).
  • Handlers: objetos que procesan mensajes. Un handler puede estar compuesto de otros handlers.
  • Actions: puntos con nombre para entrar a un handler

Un ejemplo de definición de aplicación en AjMessages.SampleApp\Configurations\Server1.xml:

<?xml version="1.0" encoding="utf-8" ?> <AjMessages> <Application Name="AjMessages"> <Node Name="Administration"> <Handler Name="ConfigureHandler" Type="AjMessages.ConfigureHandler, AjMessages"/> <Handler Name="PrintHandler" Type="AjMessages.PrintHandler, AjMessages"/> <Handler Name="PrintMessageHandler" Type="AjMessages.PrintMessageHandler, AjMessages"/> <Handler Name="ConfigurePipeline"> <Handler Name="PrintHandler"> <Property Name="Text" Value="Reconfiguring server..."/> </Handler> <Handler Name="ConfigureHandler"/> </Handler> <Action Name="Configure" Handler="ConfigurePipeline"/> </Node> </Application> <Application Name="App1"> <Node Name="Node1"> <Handler Name="PrintMessageHandler" Type="AjMessages.PrintMessageHandler, AjMessages"/> <Handler Name="PostHandler" Type="AjMessages.PostHandler, AjMessages"/> <Handler Name="DecrementHandler" Type="AjMessages.SampleApp.Handlers.DecrementHandler, AjMessages.SampleApp"/> <Handler Name="Pipeline1"> <Handler Name="DecrementHandler"/> <Handler Name="PostHandler"> <Property Name="Action" Value="App1/Node1/Process"/> </Handler> </Handler> <Action Name="Process" Handler="Pipeline1"/> </Node> <Node Name="Node2"/> </Application> <Host Name="Server1" Activate="true"> <Application Name="AjMessages"> <Node Name="Administration"/> </Application> <Application Name="App1"> <Node Name="Node1"/> <Node Name="Node2"/> </Application> </Host> <Host Name="Server2" Address="http://localhost:50002/ajmessages/node"> <Application Name="AjMessages"> <Node Name="Administration"/> </Application> <Application Name="App1"> <Node Name="Node1"/> <Node Name="Node2"/> </Application> </Host> </AjMessages>

Ejecutando el ejemplo

Abrimos la solución en el Visual Studio 2008 (se necesita tener instalado un Microsoft Robotics Developer Studio, una versión CTP de este año, debe configurar el directorio de salida de los proyectos para que apunten a su directorio de MRDS). Al ejecutar el proyecto DSS se lanza un DSS Host, que muestra una ventana de control:

El host está ejecutando en las puertas 50000/50001. Configure el servidor AjMessages usando el archivo AjMessages.SampleApp\Configurations\Server1.xml.

Podemos lanzar un segundo host desde el prompt de DSS:

bin/dsshost /p:50002 /t:50003
m:<pathto>\Source\AjMessages.DssServices\AjMessagesDssServices.manifest.xml

Un segundo formulario aparece:

Use el archivo de configuración AjMessages.SampleApp\Configurations\Server2.xml y el port 50002.

Podemos enviar un mensaje a la aplicación de ejemplo (que ejecuta en dos hosts). El mensaje es solamente un entero, que es decrementado en cada proceso de acción en cada nodo. El nodo de decremento está instalado en ambos servidores, así que el mensaje viaja de uno a otro durante su proceso.

Próximos pasos

Quiero mejorar varios puntos. Me gustaría serializar cualquier tipo de mensaje, ahora solamente viajan enteros y strings. Me gustaría usar un solo archivo de configuración, en lugar de uno por máquina. Y poder tener en una sola solución, ambas implementaciones de hosting y transporte: DSS/CCR y WCF.

Nos leemos!

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

CCR usado en mensajes asincrónicos

Friday, September 19th, 2008

Leo en el blog de Arvindra Sehmi que la gente de Tyco Software House implementó un sistema donde usando CCR (Concurrent and Coordination Runtime), la librería que viene dentro de Microsoft Robotics. En su artículo ARCast.TV – Nice Example of CCR Adoption in the Enterprise muestra el video donde la gente de Tyco explica cómo consiguieron procesar gran cantidad de mensajes, basándose en envío asincrónico.

ARCast.TV – Stephen Tarmey of Tyco on adopting Robotics Studio CCR for High Performance Async IO
 

Me gustaría que mostraran algo más gráfico del sistema que armaron, pero igual es interesante escuchar a alquien que usa a Microsoft Robotics aplicado a la empresa.

Ya Arvindra había comentado usos de DSS/CCR más allá de Robotics en

DSS Use Cases in the Enterprise

Todavía algunos de esos usos no están publicados, pero espero que aparezcan más casos de éxito con el tiempo.

El año pasado escribí y publiqué un ejemplo AjMessages, con intercambio de mensajes asincrónicos, usando WCF como comunicación entre nodos de una grilla:

AjMessages- hacia un procesador de mensajes

También el año pasado escribí una versión para usar CCR internamente, y DSS como comunicación entre los nodos, pero no la publiqué. El núcleo del sistema se puede implantar en un host WCF o en un host DSS. Me gustaría en estos días, pulir un poco el código, y publicar el ejemplo, para ver que uno puede usar CCR internamente para encolar mensajes en memoria, y repartirlos en un pool de threads que maneja internamente CCR, mientras al mismo tiempo, repartimos mensajes en otros nodos de la grilla, si los hubiera, sin mayor problema, para conseguir escalabilidad usando más máquinas de forma transparente. Como ejemplo de uso, podría reescribir el Web Crawler o el programa de Fractal, que escribí directamente para DSS/CCR/VPL:

Agentes Distribuidos y Fractales usando DSS/VPL

Agentes Distribuidos usando DSS/VPL

Pero imaginen que pueden repartir una tarea entre varias máquinas, incluso remotas. Imaginen que pueden enviar una tarea a realizar (como recolectar información para un informe de Business Intelligence) a una sucursal, y otra tarea a máquinas de otra sucursal dentro de su empresa. Pueden recibir los resultados como mensajes, usando un patrón del tipo request-response. Podemos codificar “agentes” que se envíen mensajes entre sí, para colaborar en un objetivo.

Creo que el modelo de mensaje asincrónico junto con la implementación de grilla, puede ser explotado de muchas maneras. Mi idea es aprovechar mi semana sabática (que comienza mañana) para codificar algunos proyectos, y uno de ellos es una versión más terminada de AjMessages.

Nos leemos!

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

Recursos de Grid Computing

Saturday, May 10th, 2008

Desde el año pasado, y más en estas últimas semanas, he estado investigando sobre Grid Computing, buscando enlaces, recursos, “papers”, implementaciones. Este post es el resultado de esa investigación.

Como siempre, un artículo de la Wikipedia:

http://en.wikipedia.org/wiki/Grid_computing

Si Ud. se está iniciando en el mundo de Grid Computing, estas son buenas introducciones

New to Grid Computing

Grid Computing according IBM

The anatomy of the grid

The physiology of the grid  

Interesante lista de lecturas para desarrolladores en Grid

Recommended reading list for grid developers

Grid Café tiene varios artículos y recursos

Grid Cafe Grid Projects in the world  

Grid Cafe The place for everybody to learn about the Grid  

What is “the Grid”?  

Grid @ CERN 

Sobre el estado de la industria:

http://www.gridtoday.com/ (un poco demasiado abarcativo, no es sólo sobre grid computing)

http://www.gridblog.com/

La lista completa de enlaces que mantengo, en:

http://del.icio.us/ajlopez/gridcomputing

Algunos productos para examinar:

http://www.gridgain.com
http://www.digipede.net algo más sobre Digipede en http://dotnetjunkies.com/WebLog/stefandemetz/archive/2006/12/09/Free_Grid_Computing_software.aspx
http://www.gridgistics.net/

http://sourceforge.net/projects/ngrid/

Algo relacionado, que comienza a “estar de moda”:

http://en.wikipedia.org/wiki/Cloud_computing

He escrito artículos en este blog sobre Grid Computing:

http://msmvps.com/blogs/lopez/archive/tags/Grid+Computing/default.aspx

y en “Anglish”, Angel’s English:

http://ajlopez.wordpress.com/category/grid-computing/

donde hay algunas implementaciones sencillas de ideas a seguir explorando, como AjAgents, y AjMessages.

Esta lista de recursos, en Anglish, desde:

Grid Computing Resources

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

Agentes en Grid

Thursday, May 8th, 2008

El año pasado participé del desarrollo de una aplicación que se ejecuta en una grilla de máquinas sin disco. Este año, estoy volviendo a actualizar el proyecto, espero poder bloggear sobre el resultado dentro de un mes. Mientras, quisiera escribir sobre algunas ideas a explorar.

En este post, uso el término “agente”, de una forma algo libre. No definiré precisamente el concepto, quiero usarlo como término base a refinar en el futuro (llegando en algún momento a tratar el tema de agentes autónomos, que me parece más interesante). Por ahora, exploremos algunas ideas básicas (¿ingenuas?) para entender mejor los problemas relacionados con agentes y aplicaciones en grid. Algunas de las ideas acá presentadas pueden ser vistas como ingenuas, pero siento que es un ejercicio necesario, para aprehender los conceptos clave y los problemas a ser resueltos en este tipo de aplicaciones. Al final de este post, presentaré algunas sugerencias de implementación.

He descripto algunas aplicaciones para ejecutar en una grid en mis anteriores post:

Grid Computing Programming

Más programando para una grid

Programando para una Grid

Conceptos de Agentes

En este post, un agente es una pieza de software, con conducta y estado. Se ejecuta en un host de agentes, una aplicación que provee los servicios de base para que el agente pueda “vivir” y trabajar. Representaremos al agente con esta figura:

Patrones de comunicación de agentes

Hay mucha literatura sobre comunicación de agentes, desde simples técnicas hasta elaborados contratos, negociaciones, y más. Podemos tener agentes con creencias, deseos e intenciones. En este post, un agente es más simple: sólo tiene estado, puede enviar y recibir mensajes. Puede recibir estímulos de otros agentes y desde el ambiente de su host.

El más simple patrón de comunicación es un agente enviando un mensaje a otro agente:

Algunas notas:

– El agente enviador conoce al agente receptor. Quiero decir, alguna forma de identidada debe ser implementada. El mensaje no es enviado a cualquiera: el que envía intenta enviar el mensaje a un determinado agente.

– El mensaje transporta datos, y debe ser entendido por el receptor, posiblemente procesado por uno de sus métodos de implementación.

– En enviador no espera por una respuesta. No está interesado en un mensaje de respuesta inmediato.

– Los agentes pueden residir en diferentes máquinas en la grila, y la comunicación se produce tanto local como remota.

Durante su vida un agente puede enviar muchos mensajes a distintos agentes, que debe conocer de alguna manera:

Algunas veces, el agente enviador recibirá un mensaje desde el agente receptor, notificando algun trabajo hecho, o enviando algún dato procesado. Dependiendo de la aplicación, el mensaje de respuesta podría acarrear información para identificar al mensaje original:

En este caso, el enviador original debe estar preparado para recibir la respuesta de una manera asincrónica. Esto podría ser un interesante problema a resolver: un agente puede enviar varios mensajes, y sería mejora si puede seguir ejecutando sin recibir todas las respuestas a tiempo. Por ejemplo, en una aplicación de un juego de tablero, un agente puede delegar la exploración de un árbol de jugadas a otros agentes, y, luedo de un tiempo, sería posible tomar una decisión, con sólo algunas respuestas recibidas.

Nubes (“clouds”) en el cielo de la grilla

Otro caso: un agente puede estar interesado en enviar un mensaje, pero no a un receptor determinado. Al contrario, quiere enviarlo a una “nube” de agentes, así cualquiera interesado en el mensaje tendría la oportunidad de procesarlo.

Esta característica puede ser implementada usando estas estrategias:

– Un agente envía un mensaje a un sistema de pizarra (blackboard), que otros agentes están vigilando.

– Una agente enviaría una mensaje a la aplicación host, indicando un tópico (como en una cola de mensajes), así cualquier agente subscripto recibirá el mensaje. Una variante: sólo algunos subscriptores reciben el mensaje, dependiendo de parámetros de aplicación.

– Un agente podría enviar un mensaje dirigido a alguna definición de proveedor de servicio. Un proveedor de servicio es un agente, que declara al comienzo de su vida, sus capacidades y los servicios que puede proveer. 

Un ejemplo, tomemos una aplicación de un juego de tablero, ajedrez o go. Un agente en esa aplicación puede enviar un mensaje reclamando resolver cierta posición de ataque. En un sistema de pizarra, publicará el pedido. En un sistema de tópicos, lo enviaría al tópico “ataques”. En una estrategia de proveedor de servicio, envía el mensaje a uno o más de los proveedores del servicio AttackResolver.

Como en el patrón anterior, un agente puede recibir una respuesta asincrónica, ahora desde “la nube”:

 

Duplicación de agentes

Un agente tiene conducta y estado. Si el agente puede dividir su trabajo, podría tomar el camino de duplicarse a sí mismo:

Es algo extraño, pero podría ser útil, dependiendo de la aplicación a desarrollar.

Agentes y la Grilla

Cada agente puede ser albergado en un nodo de la grilla. El mecanismo de envío de mensajes debe ser capaz de enviar un mensaje a otro nodo. La aplicación host mantiene una lista de agentes por identidad, y conoce cúal  es local o remoto. Una prueba ácida: una aplicación de grilla con agentes debe ser capaz de correr en una sola máquina, o en una grilla, sin cambiar el código o el algoritmo.

 

Como en otras implementaciones de grilla (discutidos en los post que mencioné al principio), un servidor central está a cargo de la distribución de las tareas entre los nodos de la grilla. “Grid as a Service” es una nueva frase que podemos aplicar a esta situación.

Moviendo al Agente

Un agente puede iniciar sus actividades en un node. Pero en algún momento, puede decidir de continuar su trabajo en otro nodo (la aplicación host que lo alberga también puede tomar esa decisión, independientemente del agente). Entonces, su estado sería enviado de un nodo a otro (otro caso: podría querer duplicarse y que su clon siga el trabajo en otra máquina).

Noten que la conducta del agente (que puede estar compilada o puede estar escrita en un lenguaje dinámico o de agente), no viaja. Pero bien podría ser que viaje, incluso, que haya agentes que vayan adaptando su conducta en el tiempo.

Inyectando conducta

La conducta de cada agente podría ser expresada en código compilado (archivos .jar en Java, assemblies en .NET). Otras alternativas son posibles: la conducta podría ser especificada en un lenguaje de scripting dedicado a agentes (pienso en una adaptación del AjBasic, por ejemplo).

Si la conducta se expresa en forma compilada, uno o varios servers puede tomar la responsabilidad de almacenar y distribuir esos componentes:

Ideas de implementación

Muchas de estas ideas pueden ser implementadas en cualquier lenguaje/tecnología apropiada, como Java y .NET, que soporte múltiples threads, invocación remota, serialización de mensajes, etc…

En los últimos tiempos estuve trabajando en mis projectos AjMessages y AjAgents, más información enestos post:

AjMessages: a message processor

Agents using Concurrency and Coordination Runtime (CCR)

AjMessages- hacia un procesador de mensajes

Agentes usando Concurrency and Coordination Runtime (CCR)

Algoritmos Genéticos con AjAgents y Concurrency and Coordination Runtime (CCR)

Genetic Algorithms with AjAgents and Concurrency and Coordination Runtime (CCR)

(Tengo otro proyecto, AjGrid, no publicado aún). Para este post, creo que el AjAgents podría ser una implementación de esas ideas. AjMessages tiene ahora soporte de ejecución remota, pero está más orientado a un proceso tubería (“pipeline”): es más difícil de implementar en semejante sistemas las ideas de este post.

Estoy agregando algunas características a AjAgents (ahora, AjAgents trabaja sólo en local):

Configuración: Carga y creación de agentes en ejecución, según alguna información de configuración, ya sea al inicio o en el medio de la ejecución.

Assembly remoto: Así un nodo de grilla pueder ser inyectado con nuevos agentes.

Identificación de Agente: Para identificar al agente de manera única (un UID debería bastar).

Transporte de mensaje: Windows Communication Foundation es un candidato, otro podría ser DSSP.

Un posible camino es tomar Decentralized System Services (DSS) del Microsoft Robotics Developer Studio. Un agente podría ser implementado como un servicio de DSS, ejecutando en un host DSS. La comunicación entre máquinas puede ser implementada usando DSSP como protocolo.

“Stay tuned”, vendrá más código.

(Esta es una actualización y traducción de mi post en “Anglish”, Angel’s English:

Agents in a Grid

)

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

AjMessages: hacia un procesador de mensajes

Monday, October 22nd, 2007

Siguiendo las ideas del proyecto Fabriq, estuve escribiendo un ejemplo de una aplicación servidora que puede recibir y procesar mensajes OneWay de  Windows Communication Foundation (WCF). El servidor ejecuta un concepto lógico, una aplicación: cada aplicación tiene nodos, que a su vez contienen acciones. El ejemplo puede bajarse de AjMessagesWCF-0.1.1.zip

El mensaje

El mensaje a comunicar es un mensaje WCF (en la versión original de Fabriq no se usa WCF). La información principal que AjMessages usa está en la propiedad Headers.Action. Ese texto tiene el nombre de la aplicación destino, el nodo y la acción a invocar.

La acción

Tiene el formato:

<application>/<node>/<action>

Una aplicación tiene un conjunto de nodos. Un servidor puede albergar uno o varios nodos de una aplicación. Un nodo puede ejecutarse en distintos servidores. De esta forma, el proceso interno del servidor puede reenviar un mensaje a otro servidor: la acción no es una dirección física, sino que es lógica. Cada server conoce la dirección y nodos en ejecución de los demas, porque se le informa en un archivo de configuración, o dinámicamente durante la misma ejecución. Con esa información puede reenviar un mensaje a otra máquina.

La aplicación

Un archivo de configuración XML define las aplicaciones que un servidor conoce. Una aplicación tiene:

  • Nodes: cada nodo es un conjunto de acciones a procesar. Nodo es a acción, como clase es a método.
  • Handlers: los objetos que procesan un mensaje. Un handler puede estar compuesto de otros handlers.
  • Actions: los puntos de entrada con nombre a un handler

Un ejempl de definición de aplicación:

<Application Name="App1"> <Node Name="Node1"> <Handler Name="PrintMessageHandler" Type="AjMessages.PrintMessageHandler, AjMessages"/> <Handler Name="PostHandler" Type="AjMessages.PostHandler, AjMessages"/> <Handler Name="DecrementHandler" Type="AjMessages.Console01.DecrementHandler, AjMessages.Console01"/> <Handler Name="Pipeline1"> <Handler Name="DecrementHandler"/> <Handler Name="PostHandler"> <Property Name="Action" Value="App2/Node1/Process"/> </Handler> </Handler> <Action Name="Process" Handler="Pipeline1"/> </Node> <Node Name="Node2"/> </Application>

El handler

Un handler debe implementar la interfaz:

public interface IHandler { void Process(Context ctx); }

El contexto tiene una propiedad Message, que apunta al mensaje WCF en proceso. También tiene otros métodos para usar: una propiedad Server que referencia al servidor en ejecución, y un método Post para enviar un nuevo mensaje. La idea es colocar en el contexto todo lo necesario para que un handler se comunique con el proceso en ejecución.

Esta es una diferencia con la implementación original de Fabriq, donde un handler recibe un mensaje, no un contexto.

El host

Un host es una unidad lógica que se ejecuta dentro de un servidor AjMessages. Un servidor conoce via configuración cuáles son los hosts que tiene disponibles remotamente, y cuáles levantar localmente. Un ejemplo:

<Host Name="Host1" Address="http://localhost:50000/AjMessages" Activate="true"> <Application Name="AjMessages"> <Node Name="Administration"/> </Application> <Application Name="App1"> <Node Name="Node1"/> <Node Name="Node2"/> </Application> </Host>

Configuración dinámica

Uno de las características claves implementadas es un handler que reconfigura al servidor durante la ejecución, en runtime. Recibe una nueva configuración XML, en un string, y con eso actualiza la configuración que tenga en ese momento. Usando este handler, una aplicación puede enviar un mensaje al servidor AjMessages, y cargar, parar, actualizar hosts, aplicaciones y nodos.

La solución

 El proyecto de librería de clases AjMessages contiene la implementación del ejemplo. Los otros proyectos son tests manuales que muestrar el uso de la librería.

Dentro de la carpeta Configuration hay clases definidas para leer la configuración desde un XML.

La carpeta Handlers contiene algunos handlers ya definidos, el más importante es el ConfigurationHandler que permite reconfigurar dinámica al servidor mientras está en ejecución.

La carpeta Ports tiene implementaciones de endpoints para recibir y enviar mensaje a otro servidor AjMessages.

El PipelineHandler.cs es el hadler compuesto, que contiene otros handler.

LocalHost.cs es la implementación de un host que se está ejecutando en el mismo server. Mantiene una lista de los nodos activos.

RemoteHost.cs mantiene la información asociado a los hosts que se ejecutan en otros servidores. Con esa información, el servidor local conoce cómo reenviar un mensaje, al saber qué servidores remotos tienen un nodo apropiado para la acción del mensaje.

Ejecutando el ejemplo

Hay un proyecto de consola AjMessages.Console01 que puede ser usado como un test manual, para probar el funcionamiento del ejemplo.

Se puede ejecutar el ejemplo, y al lanzarlo, pide comandos por la consola. Una prueba posible es la siguiente:

load ConfigurationServer1.xml
load ConfigurationHost1.xml
load ConfigurationHost2.xml
send App1/Node1/Process 20

El primer comando crear el servidor, usando el archivo de configuración. El segundo y tercer comando reconfigura el servidor para instalar y ejecutar dos hosts, con sus aplicaciones y nodos. El último comando envía un mensaje entero usando la acción App1/Node1/Process.

Luego, podemos ingresar:

unload
fork

Esto lanza otro servidor de consola. En el primer servidor, ingresamos:

load ConfigurationServer1.xml
load ConfigurationHost1.xml
load ConfigurationRemoteHost2.xml

y en el segundo:

load ConfigurationServer2.xml
load ConfigurationHost2.xml
load ConfigurationRemoteHost1.xml

En cualquier de los dos, ingresamos:

send App1/Node1/Process 20

y vermos a los dos servidores intercambiar mensajes.

En cualquier momento, al ingresar:

help

obtenemos una lista de comandos a usar.

Próximos pasos

En una futura versión, reescribiré el ejemplo para usar un Message propio, capaz de ser transportado via WCF o DSS (Decentralized System Services). Así, el servidor podrá albergarse en otras tecnologías. Debo refactorizar algunas clases, como Server, que ha quedado con muchas responsabilidades.

Nos leemos!

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