AjMessages: hacia un procesador de mensajes

Published on Author lopezLeave a comment

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/

Leave a Reply

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