Archive for the '3282' Category

Programando Juegos Sociales en Línea (Parte 5) Nuevo Azure Toolkit

Thursday, December 1st, 2011

Anterior Post 
Siguiente Post 

Dos semanas atrás, fue publicada una nueva versión del Windows Azure Toolkit for Social Games. Vean los posts de @ntotten:

Windows Azure Toolkit for Social Games Version 1.1.1
Windows Azure Toolkit for Social Games Version 1.1

La nueva versión implementa dos juegos simples en HTML5: Ta Te Ti, y Cuatro en Raya, usando vistas ASP.NET MVC, servicios WCF Web API, seguridad federada usando ACS, y Azure Storage. Pueden jugar en línea en:

http://watgames4.cloudapp.net/

Pienso que éste es un ejemplo más claro que el anterior (Tankster) que era una gran aplicación pero algo excesiva ;-). Veamos de entrar en algunos detalles de implementación de este nuevo ejemplo.

Totten escribió:

The biggest change we have made in this release is to separate the core toolkit from the Tankster game. After we released the Tankster sample game we received a lot of feedback asking for a simpler game that developers could use to learn. To meet this need we developed two simple games, Tic-Tac-Toe and Four in a Row, and included in the toolkit. The Tankster game is now available separately as a sample built on top of the toolkit.

While the new games included in the toolkit are much simpler than Tankster, they still show the same core concepts. You can easily use these samples as a starting point to build out any number of types of games. Additionally, you will find that many of the core components of the game such as the leaderboard services, game command services can be used without any modification to the server side or client side code.

En mi anterior post, mencioné un pequeño pero importante cambio en el proceso de acciones de juego: toda la lógica fue removida del código del servidor. Adoptando este camino, podemos escribir nuevos juegos sin cambiar el código del servidor. Podemos seguir agregando código en el servidor si lo necesitamos (por ejemplo, para agregar control al juego, detectar operaciones inválidas enviadas desde algún cliente, etc) pero es interesante tener una base de código que sea agnóstica del juego.

Abriendo la solución en Visual Studio, encontraremos archivos Javascript usados por los dos juegos. Podemos escribir un nuevo juego, reusando estos archivos sin cambios:

Los juegos están implementados como áreas:

Podríamos escribir nuevos juegos y publicarlos como paquetes NuGet.

Visualmente, el código Javascript cliente está organizado de esta manera:

Cada juego X (X = Ta Te Ti, Cuatro en Raya, uno nuestro) tiene:

XGame: la lógica del juego

XBoard: para dibujar el tablero en un elemento canvas de HTML5, y para detectar eventos de click en el mismo.

XViewModel: contiene el jugador actual y otros datos para ser usandos en el armado de la vista (los ejemplos usan  knockout.js, como MVC en Javascript)

XController: para procesar nuevos eventos y para coordinar los elementos de arriba.

La parte genérica:

UserService: métodos relacionados a usuarios: login, lista de amigos, etc…

GameService:  jugar las movidas, recibir movidas de otros jugadores, otras acciones (por ejemplo, se podrían enviar mensajes de chat).

ServerInterface: Llamadas Ajax (usando GET, POST, JSONP, Azure storage….) que son usados por la implementación de User y Game Service.

Temas para próximos posts: analizar el código Javascript, el uso del Canvas, tests de Javascript usando QUnit, comunicación con el servidor usando Ajax, cambio del Game Service (en Javascript) para usar un Node.js como servidor que reciba y reparta las acciones de juego.

Nos leemos!

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

Programando Juegos Sociales en Línea (Parte 2) Tankster y Windows Azure Toolkit For Social Games

Friday, July 22nd, 2011

Anterior Post
Siguiente Post

El miércoles pasado, 20 de Julio, Microsoft liberó una versión “preview” del Windows Azure Toolkit for Social Games, y publicó una versión beta (con código) de un primer juego de demostración.

Pueden bajar el código desde Codeplex: http://watgames.codeplex.com/

Pueden jugar el juego en línea en: http://www.tankster.net/

La solución actual tiene estos proyectos:

Tankster.GamePlay es un Web Role. Hay un único WorkerRole. Tankster.Core es una librería de clases. Hay código interesante en Tankster.Common: utilitarios Azure para acceder a repositorios, un “job engine”, y más; todo ese código es independiente del juego, podría usarse en cualquier proyecto Azure.

Estos son mis primeros cortos comentarios sobre el código y la implementación de las “features” de este juego (recuerden, es un beta! Algunas de estas implementaciones podrían cambiar en el próximo “release”):

– Tecnología cliente: HTML5, Javascript, EaselJs (para programación del canvas, que permite implementar la parte gráfica).
– Tecnología servidor: ASP.NET MVC 3, algunas vistas Razor para pruebas (tema interesante: ¿Cómo probar el juego cuando sin usar el juego REAL), WCF Web API (otro tema interesante: ver tecnologías alternativas para manejar la actividad del juego. Es importante: un tema a cuidar en este tipo de aplicaciones es cómo responder a una gran carga desde el cliente)

– Hay un modelo en el cliente y entidades en Javascript. Vean See src/model, src/game.

– Hay un modelo del juego There is a server game model (see Tankster.Core class library project)

 

– Pueden jugar en modo “single player” o pueden elegir “multi-player online”. En este caso, el juego usa el ACS Portal para permitir la autenticación usando Federated Authentication:

– El código cliente reside en una sola página: index.html (con montones de archivos javascript referenciados desde ahí)
– El código cliente envía JSON (comandos) a los WCF Web API endpoints, usando Ajax/JQuery. Hay varios servicios publicados, exponiendo una interfaz tipo REST

routes.MapServiceRoute<GameService>("game");
routes.MapServiceRoute<AuthService>("auth");
routes.MapServiceRoute<UserService>("user");
routes.MapServiceRoute<TestService>("test");

– Mucha de la actividad del juego es enviado al servicio game/command. El servicio (en el web role) actualiza el estado del juego guardándolo en un blob en el Azure Storage. Fragmento de código:

// Add gameAction
var gameAction = new GameAction
{
    Id = Guid.NewGuid(),
    Type = commandType,
    CommandData = commandData,
    UserId = this.CurrentUserId,
    Timestamp = DateTime.UtcNow
};
// Cleanup game actions lists
for (int i = 0; i < game.GameActions.Count(); i++)
{
    if (game.GameActions[i].Timestamp < DateTime.UtcNow.AddSeconds(-10))
    {
        game.GameActions.RemoveAt(i);
        i--;
    }
}
game.GameActions.Add(gameAction);
this.gameRepository.AddOrUpdateGame(game);

– El estado del juego es “poleado” por los clientes javascript consultando directamente el blob storage. De esta forma, el Web Role ASP.NET MVC tiene menos carga.
– El blob reside en el mismo dominio, así que no son necesarias llamadas Ajax cross-domain. Pero el juego está preparado para ese tipo de llamadas, reemplezando el objeto XmlHttpRequest por un componente Flash.
– El modo de juego Skirmish (cinco jugadores en una batalla) está hecho encolando los jugadores hasta llegar a cinco. Ese trabajo lo hace el Worker Role. Va publicando el estado en un blob que es “poleado” por los clientes.
– Las estadísticas son procesadas en el worker role: los clientes javascrip envían comando al Web Role, éste selecciona algunos para estadísticas y los envía a una cola Azure. No se ocupa de las estadísticas en el momento, para no afectar al cliente. Finalmente, esos datos para estadísticas se manejan en el Worker Role.
– User status, Game status, Skirmish Game Queue status son blobs.
– Las estadísticas se guardan en SQL Azure.
– El único worker role tiene un Job Engine (motor de trabajos) para procesar varias tareas, ejemplo “fluent”:

// Game Queue for Skirmish game
Task.TriggeredBy(Message.OfType<SkirmishGameQueueMessage>())
    .SetupContext((message, context) =>
    {
         context.Add("userId", message.UserId);
    })
    .Do(
        new SkirmishGameQueueCommand(userRepository, 
            gameRepository, workerContext))
    .OnError(logException)
    .Start();

Hay varios puntos para comentar y discutir, alimento para futuros posts. Seguramente la solución actual evolucionará y nuevas versiones serán publicadas (¿esta semana? ¿la próxima?). Pero es interesante ver publicado un juego en línea y su código disponible para analizarlo.

Nos leemos!

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

Locura en la configuración de Windows Communication Foundation

Thursday, March 5th, 2009

Windows Communication Foundation fue creado para permitir la creación de aplicaciones distribuidas, dándonos una librería de herramientas de comunicación que podemos reusar, sin necesidad de escribir el Service Interface y el Service Gateway desde cero. Tecnologías como servicios web han evolucionado, tienen varias versiones y detalles a tener en cuenta si queremos una comunicación segura, confiable y que soporte interoperabilidad.

El concepto de un Service Model, es ungran avance. Pero hoy, quiero levantar mi mano, para apuntar a algo que hace a WCF una solución”convoluted”. Me refiero a la configuración de WCF.

Si uno quiere usar cualquier característica de WCF, más allá de las más simple, se encontrará rápidamente peleándose con las opciones de configuración de esta bestia. ¿Un síntoma? Si Ud. se olvida de una mínima parte, el canal no funcionará. Si Ud. omite alguna opción de configuración cuando crea un certificado, y se olvida de hacer un paso, entre una docena de pasos de una “to do list”, la llamada via WCF no podrá ser completada. Y tendrá que manejar una cantidad de conceptos, como certificados, tokens, issers, chain of trusts, behaviors, bindings, endpoints, identities, custom bindings, factories, service hosts, channel factories, security options, enumeration types, extensions methods, and… Podría continuar enumerando por horas.

Un ejemplo mínimo. Buscando por la web, encuentro el artículo

WCF (Windows Communication Foundation) Example

Leo ahí:

Being able to switch the transport layer from TCP (Secure SSL) into HTTP with some simple code, that’s amazing!

Sí, correcto, pero

I did have some problems, though. The tcpBinding.Security.Mode = SecurityMode.None; is very crucial on both sides. I’m not sure what it does, but it does not turn off the security completely as I have read in my references. There is still SSL encryption, but on a lower level. It is possible to add certificates to the connection, which also makes the connection more secure.

Acá está el problema. Si uno juega explorando las distintas propiedades y métodos de los bindings y endpoints disponibles, entraremos en un laberinto sin salida visible. Notemos que el autor del artículo no está seguro sobre una de las opciones de configuración que está usando. Y eso que es una sola opción: hay docenas más para configurar, si uno quiere hacer ajuste fino del servicio.

Claro, hay configuración declarativa, no por código. Y hasta podemos usar el  WCF configuration wizard:

Ok, ¿pueden ver los tres tabs, a la derecha? ¡Son más opciones para llenar y entender! ¿Pueden ver el árbol a la izquierda? Es sólo la punta visible de un iceberg. Si expandimos la rama de bindings, entraremos en nuevo mundo de Narnia:

Más propiedades para llenar, ¡y más tabs! Empezará a sentirse incómodo. Si tiene coraje, cree y expanda cualquier cosa en el branch advanced:

El árbol comienza a parecerse a una selva amazónica. Podría tomar capturas de pantallas de cada una de las ramas que el wizard expone, en tal cantidad que podría publicar un volumen completo.

Mucas de estas opciones SON REQUERIDAS si queremos asegurar la comunicación de nuestro servicio, usar tokens emitidos por otras máquinas, definir la autenticación del cliente que invoca y el servicio que atiende, y más. Mi punto es: si Ud. falla en llenar y definir una mínima parte de todo esto, su sistema será un castillo de arena, una torre de cartas en delicado equilibrio. Parace un efecto mariposa: el vuelo de una mariposa en un archivo de configuración, podría crear una tormenta en el resto del sistema. Deberá prestar atención a DEMASIADOS detalles. Es común tener que prestar atención a los detalles en el desarrollo de software. Pero en este caso, pienso que es demasiado: es insano para cualquier mente humana, o para un equipo de desarrollo y despliegue.

En otros sistemas, también tenemos multitud de opciones (¿recuerdan las propiedades un control de formulario?). Pero uno no conocerlas en profundidad a todas (ni siquiera a la mitad), para conseguir algo útil. No es el caso con la configuración de WCF. Este estado de las cosas, apesta. Y si uno quiere escribir directamente en el XML de configuración, terminará con quizás cientos de líneas como:

 

Hay pocas cosas más feas que haya encontrado en mis treinta años de desarrollo (podría enumerar: configuración de EJB, ideas de Cocoon, el Job Control Language en los mainframes IBM…).

Tengo una teoría. Enrico Fermi preguntaba: si los extraterrestres existen, ¿dónde están? ¿por qué no vemos ninguno? La historia es: ellos existen. Comenzaron a estudiar nuestro planeta hace décadas (recuerden, los primeros avistamientos se dieron cerca del Monte Rainier, ¡sí! cerca de Seattle, ya comenzaban a darse cuento que por ahí comenzaba a haber algo raro). Por años, leyeron nuestra literatura, vieron nuestra producción fílmica, hicieron experimentos controlados con seres humanos elegidos. Pero cuando hace unos años comenzaron a estudiar la configuración de EJB y WCF, nuestro planeta estuvo condenado: lo declararon en cuarentena, nadie puede contactarnos, estaremos aislados del resto de la galaxia por diez mil años. La humanidad es una loca civilización, no esperanza sobre nuestro futuro. Nadie puede visitarnos, para que la locura de EJB y WCF no se expanda.

Ok, paro de quejarme. WCF tiene un gran modelo de servicio: ahora, puede manejar JSON, XML, y está preparado para ser flexible y extensible. Pero algunas veces, debemos parar la pelota, y poner en la balanza, no sólo la flexibilidad, sino también la complejidad de la que viene acompañada. Espero escribir posts más positivos, con ejemplos concretos, pero este post ha sido el resultado de días de lucha con WCF, ejemplos, documentación y guías de implementación.

Nos leemos!

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

Programando para una Grid

Thursday, November 15th, 2007

En anteriores posts, comenté sobre los proyectos AjMessages y AjAgents:

AjMessages- hacia un procesador de mensajes

Agentes usando Concurrency and Coordination Runtime (CCR)

Una de las capacidades que tiene AjMessages es comunicar distintas instancias del programa, que pueden ejecutar en diferentes máquinas servidoras. Se le pueden enviar mensajes de configuración dinámica, lo que permite que a cada máquina se le pueda dar un trabajo distinto. También puede configurarse para que una acción (elemento mínimo direccionable dentro de una aplicación AjMessages) pueda ser atendida en distintas máquinas. AjAgents apunta a que también en algún momento tenga agentes distribuidos, pero por ahora es una aplicación local.

AjMessages se podría distribuir de forma que un servidor pueda controlar otras instancias del sistema:

Quisiera enumerar aquí algunas de los escenarios de uso de un sistema que pueda ejecutar en una grilla de servidores, lo que se llama Grid Computing. Como toda “buzzword” tecnológica, puede tener un alcance amplio, pero tratemos de definirla.

Según el excelente artículo introductorio de la gente de IBM:

New to Grid Computing

Grid Computing permite unir un pool de servidores, sistemas de almacenamiento, y redes, en un gran sistema único, de manera que podamos manejar todos esos recursos múltiples a una tarea. Para el usuario, o la aplicación, el sistema aparece como un gran sistema único de computación.

En el caso de AjMessage, siguiendo las ideas de Fabriq, ese efecto se consigue porque los distintos servidores ejecutan una o varias aplicaciones, y sus acciones, de manera transparente.

El concepto de Grid Computing permite obtener mayor capacidad de procesamiento, sin necesidad de tener un gran sistema de hardware o software, sino apelando a repartir la carga y distribuyendo la tarea entre máquinas de línea. Dependiendo del sistema que organice esa distribución, podemos agregar más máquinas, obteniendo mejores resultados, sin necesidad de cambiar la aplicación.

Imaginen que podemos tener un conjunto de servidores, formando una grilla, y brindar ese conjunto a los usuarios que lo necesiten, para en algún momento resolver alguna tarea. Me imagino un Grid as a Service, que seguramente alguien ya está implementando.

Pero concentrémonos hoy en el tema: ¿qué casos de uso, escenarios, podemos imaginar para usar una grid?

He aquí la lista que estuve confeccionando:

Resolución de algoritmos genéticos: Un problema que tal vez no tenga un algoritmo normal de resolución, o cuya complejidad crezca con su tamaño de forma exponencial, puede llegar a ser un reto siguiendo procedimientos tradicionales. Con algoritmos genéticos, podemos ir probando soluciones parciales, y mediante cambio y selección, ir descubriendo mejores soluciones. Es claro que eso se puede hacer en paralelo, siendo ideal para ser dado como tarea a una grid. Me gustaría procesar algo como lo de http://www.darwinathome.org.

Búsqueda en árbol: en muchos problemas de inteligencia artificial, es necesario explorar ramas en un árbol de búsqueda. Uno de los casos donde se aplica, es en el análisis de jugadas de un juego, pero también en decisiones de negocio y planeamiento. Me imagino una grilla colaborando en la decisión de la próxima jugada en un juego de Go, uno de los problemas difíciles de la inteligencia artificial actual, ver ….)

Araña e indexador en la web: la tarea de examinar un sitio, tomar el contenidos de sus páginas, analizarlas, detectar enlaces, y seguir explorando a partir de ellos, es una tarea que bien puede ser repartida. Mientras un nodo consigue el contenido de otra página, va generando tareas para otros nodos, como analizar las páginas enlazadas desde la actual en proceso.

Trabajo en lote: podría darse a una red el trabajo de procesar gran cantidad de información que sea “partible”, desde transformaciones de una tabla de base de datos, hasta análisis de logs para generar estadísticas. Si la entrada es divisible, el proceso de cada parte puede ser enviado a un nodo distinto. Por ejemplo, un nodo se puede ocupar de transformar los datos de una tabla de transacciones, pero sólo los de enero, mientras que otro se ocupa de procesar los de otro mes

Distribución de listas de correo electrónico: Un caso típico, si somos una empresa que brinda este servicio, al llegar un correo electrónico destinado a una lista que mantenemos, delegamos el envío de cada email en particular, con personalización incluida por ejemplo, a nodos de la grilla.

Procesamiento de mensajes: Podemos necesitar recibir mensajes XML, y aplicarle transformaciones, o en base a su contenido, derivarlos a un proceso u otro. Las transformaciones y controles se los podemos deriva a nodos de la grilla. Si aumenta el caudal de mensajes entrantes, simplemente aumentamos la cantidad de nodos de procesamiento.

Ejecución de un workflow: Siguiendo con la generalización, podemos diseñar un flujo de trabajo, cada uno de sus pasos puede ejecutarse en nodos diferentes. Habrá nodos que puedan ejecutar más de un paso, y habrá pasos de toma de decisiones. Me imagino como caso concreto, la ejecución de todos los pasos ante un nuevo tenant, en un sistema encargado de provisioning de un sistema brindado como Software as a Service.

Map Reduce: Es un modelo de programación para procesar grandes conjuntos de datos. Se especifica una función Map que procesa un par clave/valor de entrada, genera pares clave/valor intermedios, en general varios. Hay otra función Reduce que se aplica a todos los pares clave/valor intermedios que compartan la misma clave. Por ejemplo, una función Map puede recibir un documento a procesar, genera pares palabra/documento por cada palabra relevante que encuentre, y la función Reduce toma esos pares de una misma palabra, para generar una lista de documentos que contengan a esa palabra. Para una explicación más detallada, ver un “paper” de Google Labs MapReduce: Simplified Data Processing on Large Clusters.

Creo que hay varias implementaciones de estos escenarios en grillas y otras soluciones. Me gustaría armar una prueba de concepto, usando el AjMessages o similar como base.

Cambiando la óptica, se puede pensar en exponer la grilla con uno o varios web services, e implementar alguna forma de poder “sembrar” trabajos desde otros sistemas en la grilla. Se me ocurre sembrar:

Assemblies completos, e invocación de algunos métodos en clases y objetos a determinar.

Programas en lenguajes de scripting, controlados por razones de seguridad

Agentes, que pueden consistir en assemblies o en código para una máquina virtual de agentes

Programas escritos en DSLs Domain Specific Language, uno o varios lenguajes que algunos nodos de la grilla entiendan.

Semejante grilla se puede brindar como servicio a otros sistemas. Surge el concepto de Grid as a Service, el alquiler de su consumo, el control del nivel de servicio, y demás, que algún software de control deberá proveer.

Ya escribiré en particular sobre Grid Computing, por ahora puede consultar el ya mencionado artículo de IBM:

New to Grid Computing

y una interesante implementación de código abierto en Java:

GridGain

(El gráfico del comienzo de este artículo está “inspirado” en uno de GridGain, pero los nodos se pueden comunicar entre sí, y repartir su trabajo, siguiendo la indepedencia de localización de cada acción en AjMessage).

Nos leemos!

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

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/

Recordando Fabriq

Sunday, October 21st, 2007

En estas semanas, estuve estudiando el código del proyecto Fabriq. Es un proyecto .NET de hace unos años, pueden bajarse el código desde este post de Arvindra Shemi:

FABRIQ has gone public!

Más información sobre el proyecto original:

Arvindra Shemi Fabriq Articles
Clemens Vasters Fabriq Articles

Una imagen de la documentación:

Según la documentación del proyecto:

FABRIQ is an infrastructure for constructing networks of nodes processing and relaying messages. These nodes are hosted in machines running into a serviced application.

Uno puede tener varias máquinas ejecutando una o varias aplicaciones. La “red” es la aplicación, un node es una colección de acciones, y cada acción procesa un mensaje. Más de la documentación:

These nodes can be hosted in any distribution on several machines according to a defined configuration, so there may be machines running a single node or several nodes, this association are made by specifying the host-name or machine identification associated with each node in the network.

Each of these machines is running a serviced application responsible for starting and stopping its Host and Nodes which are the application main components. The host is responsible for handling the configuration, loading and unloading nodes and receives the messages and delivers them to the appropriate Node.

Un post interesante que va al núcleo del problema:

Positioning FABRIQ – What? Why? Apple or Orange?

Otros artículos más técnicos:

FABRIQ Terminology
A simple FABRIQ config file
FABRIQ Message Handlers and Pipelines
FABRIQ Networks and Nodes
Configuring FABRIQ Networks and Nodes

Creo que todas estas características pueden ser reimplementadas usando las tecnologías .NET actuales, y con un poco de trabajo, en Java (el proyecto publicado usa .NET 1.x, y hostea bajo COM). En .NET podemos usar Windows Communication Foundation, o los nuevos servicios distribuidos aportados por el Microsoft Robotics (DSS).

Con WCF, el mensaje a intercambiar y procesar podría ser de la clase System.ServiceModel.Channel.Message. Otra idea podría ser tener una clase propia Message, que pueda ser serializable con diferentes transportes: WCF, DSS, Remoting, Web Services, otras.

Estoy trabajando en reescribir desde cero la idea de Fabriq, con configuración dinámica, balanceo de carga, usando WCF u otra tecnología de base. He traido algunas ideas de mi viejo proyecto AjServer:

Hacia el AjServer 

Un avance de lo que estoy haciendo, un archivo de configuración:

 

<?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="PrintMessageHandler"/> <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.ManualTest02.DecrementHandler, AjMessages.ManualTest02"/> <Handler Name="Pipeline1"> <Handler Name="PrintMessageHandler"/> <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> <Host Name="Host1" Address="http://localhost:50000/AjMessages"> <Application Name="AjMessages"> <Node Name="Administration"/> </Application> <Application Name="App1"> <Node Name="Node1"/> <Node Name="Node2"/> </Application> </Host> </AjMessages>

Tengo una versión andando, con WCF y sin WCF. Espero postear algo sobre el tema en estos días.

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

Hello World en Windows Communication Foundation

Monday, August 6th, 2007

Hay multitud de este tipo de ejemplos en la web, pero quería comentar un ejemplo en Visual Basic .NET, y sin usar archivos de configuración, para ir explicando y entendiendo, algunos conceptos de Windows Communication Foundation. El código del proyecto se puede bajar de WCFHelloWorld1.zip.

Recursos, explicaciones en inglés, ejemplos y el propio .NET 3.0 están disponibles desde:

http://wcf.netfx3.com/

http://www.netfx3.com/

 

La solución de este “post” de ejemplo consta de tres proyectos:

Todos los proyectos referencian a una nueva DLL .NET que contiene la implementación de System.ServiceModel:

Hay un proyecto consola de cliente, y otro proyecto consola con el servidor. El tercer proyecto, es una librería que define el contrato:

1 Imports System 2 Imports System.ServiceModel 3 Imports System.Runtime.Serialization 4 5 <ServiceContract()> _ 6 Public Interface IHelloWorld 7 <OperationContract()> _ 8 Function HelloWorld(ByVal name As String) As String 9 End Interface 10 11

Vemos que el contrato es una interfaz, y está adornada con el atributo ServiceContract. Cada operación de la interfaz que queremos exponer dentro del servicio WCF, deberá tener el atributo OperationContract.

El programa cliente referencia a esta librería, y por eso, conoce esta interfaz (en otros ejemplos, el cliente puede agregar una referencia a un servicio, y el generador de código del proxy cliente, construye la interfaz, pero en este ejemplo quería ir armando la relación programáticamente).

El programa servidor tiene una implementación, una clase que implementa la interfaz de servicio:

1 Imports WCFHelloWorldLibrary 2 3 Public Class HelloWorldService 4 Implements IHelloWorld 5 6 Public Function HelloWorld(ByVal name As String) As String Implements WCFHelloWorldLibrary.IHelloWorld.HelloWorld 7 Return "Hello " & name 8 End Function 9 End Class 10

 

El programa servidor, un programa de consola:

 

1 Imports System 2 Imports System.ServiceModel 3 4 Imports WCFHelloWorldLibrary 5 6 Module HelloWorldHost 7 8 Sub Main() 9 Dim host As ServiceHost = Nothing 10 ' Consider putting the baseAddress in the configuration system 11 ' and getting it here with AppSettings 12 Dim baseAddress As Uri = New Uri("http://localhost:8080/WCFHelloWorldHost") 13 14 ' Instantiate a new ServiceHOst 15 host = New ServiceHost(GetType(HelloWorldService), baseAddress) 16 Dim binding As New BasicHttpBinding() 17 18 host.AddServiceEndpoint(GetType(IHelloWorld), binding, "/HelloWorld") 19 20 host.Open() 21 22 Console.WriteLine("Press enter to end") 23 Console.ReadLine() 24 25 host.Close() 26 End Sub 27 28 End Module 29

El tipo ServiceHost es parte de System.ServiceModel, lo nuevo de .NET 3.0 que implementa Windows Communication Foundation. Es la clase que permite exponer una implementación de un servicio, en este caso, objetos del tipo HelloWorldService.

En el constructor del ServiceHost se puso el tipo que albergará, y la dirección donde se expondrá. Ahora bien, un servidor puede exponer la misma implementación, en distintos service endpoints. Cada service endpoint puede indicar lo que se llama un binding, y un nombre. Eso se agregó en la línea 18. En la línea 16 se definió que el binding será basado en HTTP básico (hay bindings más poderosos en WCF, como uno que implementa las últimas definiciones de la especificación de servicios web, puede probar también WSHttpBinding, WSDualHttpBinding, y aparecerán más en la historia de WCF). El primer parámetro de la llamada de la línea 18 es el contrato: la interfaz IHelloWorld que ya habíamos definido.

Con esos datos, el cliente puede invocar a nuestro servidor:

 

1 Imports System 2 Imports System.ServiceModel 3 Imports WCFHelloWorldLibrary 4 5 Module HelloWorldClient 6 7 Sub Main() 8 Dim cf As New ChannelFactory(Of IHelloWorld)(New BasicHttpBinding(), New EndpointAddress("http://localhost:8080/WCFHelloWorldHost/HelloWorld")) 9 Dim service As IHelloWorld = cf.CreateChannel() 10 Console.WriteLine(service.HelloWorld("Adam")) 11 Console.WriteLine("Press enter to end") 12 Console.ReadLine() 13 End Sub 14 15 End Module 16

En este cliente, se usó una clase ChannelFactory, que usa generics, y necesita que le pasemos el tipo a implementar. La factoría de canales tiene el gran método CreateChannel que devuelve un objeto que construye en el momento, que es un proxy, un objeto en el cliente, que implementa automáticamente el tipo que le pasamos como parámetro a la factoría, en este caso, un IHelloWorld. Esa es la “magia” de la factoría: analizando el tipo, implementa con generación de código (creo que usando CodeDom), todo el proxy que por debajo invocará al servidor. Dos parámetros que necesita la ChannelFactory en su construcción son el binding, y la dirección del endpoint (vemos que ésta incluye el nombre /HelloWorld). Tanto la dirección como el binding deben coincidir con el que está definido en el servidor. Pero recordemos: el servidor puede haber expuesto una implementación, con varias direcciones de endpoint y otros bindings.

Lanzamos ambos proyectos (el cliente y el servidor), ya sea configurando la solución para que lance ambos, o lanzando cada uno para depurar, o luego de armar la solución, los podemos lanzar cada uno desde una línea de comando.

Lo importante es comprender:

– El cliente sólo necesita la interfaz, el contrato, y dónde ubicar al servidor

– El servidor levanta un objeto que expone nuestra implementación, usando una dirección, binding, y contrato

Veremos más adelante que podemos implementar cómo levanta el servicio, y cómo se lo referencia en el cliente, mediante sendos archivos de configuración en ambos proyectos.

Nos leemos!

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

Beta 2 de Visual Studio 2008 y .NET 3.5 liberada!

Friday, July 27th, 2007

Ayer 26 de Julio, quedó disponible la nueva beta 2 de VS 2008 (antes conocido como Orcas). Más detalle en el blog de Scott Guthrie:

http://weblogs.asp.net/scottgu/archive/2007/07/26/vs-2008-and-net-3-5-beta-2-released.aspx

Algunas características mencionadas en ese “post”, traducidas acá:

Soporte de múltiples “targets” en VS 2008

Desde VS 2008 se pueden armar aplicaciones para múltiples versiones de .NET (no sólo para la 3.5):

Soporte de CSS y Diseño Web en VS 2008

Ahora hay un modo “split” que permite ver el diseño y el HTML de una página (lo del split también se nota en el diseñador de Windows Presentation Foundation):

Soporte de ASP.NET AJAX y JavaScript

.NET 3.5 tiene incorporado soporte ASP.NET AJAX (y con nuevas capacidades, como soporte de WebParts en UpdatePanel, y soporte de serialización JSON en Windows Communication Foundation).  VS 2008 también tiene soporte de JavaScript y AJAX “puro”:

Mejoras en lenguajes y LINQ

Los nuevos compiladores de Visual Basic y C# contienen mejoras en los lenguajes. Ambos agregar conceptos de programación funcional que permiten escribir un código más limpio, terso, y expresivo (según Scott Guthrie). Estas “features” permiten la introducción de un nuevo modelo de programación llamado LINQ (language integrated query) que hace que de las consultas y trabajo con datos un concepto de programación de “primera clase” (no algo separado) en .NET. 

Mejoras en acceso a datos con LINQ to SQL

LINQ to SQL es un OR/M (object relational mapper) incorporado dentro de .NET 3.5.  Nos permite modelar bases de datos relacionales usando un modelo de objetos .NET.  Podemos consultar la base con LINQ, así como actualizar, insertar, borrar datos con él. Provee un modo fácil de intregra lógica de negocios y reglas de validación en su modelo de datos:

(tengo un ejemplo con código en:

Linq en Orcas Beta 1

)

 

Más mejoras

En desarrollo de clientes, tenemos un diseñador de Windows Presentation Foundation. ClickOnce y WPF XBAPs funcionan ahora con FirFox. Proyectos WinForms y WPF pueden usar ahora el ASP.NET Application Services (Membership, Roles, Profile) para datos de usarios. Desarrollo con Office es más rico, con soporte del Office 2007 ribbon. Proyectos y diseñadores de WCF y de Workflow están incluidos en VS 2008. Unit Testing es soportado en VS Professional (y no sólo en VSTS).  Integración contínua es ahora parte del TFS. Testing de AJAX (unit y de load) es soportado por el VS Test SKU. Y más…

Veremos el año que viene la versión final?

Nos leemos!

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

DinnerNow, aplicación de ejemplo .NET, disponible para bajar

Thursday, February 1st, 2007

Hola gente!


Se acaba de liberar para descargar, al aplicación de ejemplo DinnerNow:


http://www.dinnernow.net


Es una aplicación que simula un mercado ficticio de restaurantes con entrega a domicilio. Usa tecnologías como Linq, IIS7, .NET 3.0, Windows Communication Foundation, Windows Workflow Foundation, Windows Presentation Foundation, Windows PowerShell, y hasta el .NET Compact Framework.


La pueden bajar desde


http://www.codeplex.com/dinnernow/release/projectreleases.aspx



Nos leemos!


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