Archive for the '13751' Category

Cuatro Reuniones en Buenos Aires: Java, Salesforce, Scala, MongoDb

Friday, August 9th, 2013

El de hoy podría ser un post largo, pero voy a tratar de hacerlo breve. Hay mucho para comentar sobre estas cuatro reunones (“meetups”) a las que asistí en estas últimas semanas.

Primero, asistí a MuleSoft, a la meetup de Java:

DSLs y Template Engines: Introducción e implementación de Handlebars.java
http://www.meetup.com/jugargentina/events/122234702/

El bueno de @edgarespina dio una charla sobre Domain Specific Language en general, mostró ANTLR 4. Luego mostró su propia reimplementación de Handlebars en Java:

https://github.com/jknack/handlebars.java

Estuvo muy interesante y bien presentada. Hmmm.. idea para code kata: reimplementar HandleBars en C#, para practicar TDD. Me alegró saber que ANTLR tiene left recursion, y que de pasada, yo también lo tengo en GrammGen y en SimpleGrammar 😉 Y ahora que ví lo que hay en ANTLR puedo extender un poco más mi propia implementación.

Hubo cervezas y sanwiches!!!! (esto es lo importante 😉

A la semana siguiente (en el salón de la justicia 😉 volví al mismo lugar, MuleSoft, pero para la meetup de Salesforce:

http://www.meetup.com/Salesforce-Argentina-Developer-User-Group/events/127462992/

Ahí me encontré con gente de MuleSoft que tiene un producto publicado que trabaja contra Salesforce, ver:

http://www.mulesoft.com/cloudhub/salesforce-integration-solutions

En el equipo esta Damian “padezeunozito” Martinez Gelabert (y una hermosa programadora, Jazmin creo, les debo el usuario de Twitter, lo mío es un apostolado ;-). La gente de Xappia:

http://www.xappia.com/index.php

estuvo a cargo de la presentación de la nueva versión de SalesForce, y del tema certificaciones. Gracias a Xappia, que me trajo el libro que me había ganado en la anterior reunión, ahora entiendo más el modelo de SalesForce. No me parece complejo lo que se puede implementar (recuerden la Tarea B de mi post), así que prometí una implementación de Force.com en dos meses desde esa fecha. Puse dos meses, porque estoy a full dando y preparando charlas. Ver mi lento avance en:

https://github.com/ajlopez/AjForce

El martes pasado asistí a la reunión de Scala, en http://www.scvsoft.com/ (vean el sitio)

http://www.meetup.com/scala_ar/events/128479882/

Sólo me pude quedar a la primer charla. Gracias al “boss”, Eric L. Miller, por más cerveza ;-). Y conocí a @jpsaraceno (y por primera vez en años, me topé con alguien que me conocía de mi charla en Smalltalks 2010, no todo está perdido ;-). @ktonga presentó un proyecto usando Akka actors, Spray, y tutti li fiocci, en:

https://github.com/ktonga/meetup-akka-spray

basado en el Typesafe Activator.

Ver también:

http://typesafe.com/blog/play-framework-akka-and-scala-adoption-in-argentina-and-Uruguay

de Jamie Allen sobre su visita a Argentina y Uruguay.

Scala es un lenguaje a estudiar. Y Akka todavía más. Mis propios experimentos implementado el modelo de actores de Akka (tengo que probar mejor lo distribuido) en:

http://msmvps.com/blogs/lopez/archive/2013/05/04/aplicaciones-distribuidas-y-node-js.aspx
https://github.com/ajlopez/SimpleActors
https://github.com/ajlopez/SimpleActors/tree/master/samples/DistributedWebCrawler

Y finalmente, ayer, fui a VHGroup:

http://www.vhgroup.net/

a la meetup de MongoDb. Fue muy interesante, conocer gente que usa MongoDb en Argentina, con millones de documentos (yo tengo un proyecto privado con unas decenas de millones de documentos, pero lo estoy pasando todo a memoria, ya saben mi predilección por el tema). Me enteré de algunos detalles que me faltaban para entender a mongodb. Así que ahora quiero hacer:

– Implementación en memoria, de un símil MongoDb con JavaScript/NodeJs
– Agregarle persistencia asincrónica
– Implementarlo en C# en memoria (con 64 bits podría albergar gigas)

Pueden ver mi primer avance (using TDD baby!) en:

https://github.com/ajlopez/SimpleMongo

Bueno, de cada reunión tendría para un post, baste por ahora este resumen. Gracias a todos los que brindan su lugar y su tiempo para que podamos reunirnos y conocernos.

Nos leemos!

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

Aplicaciones Distribuidas y Node.js

Saturday, May 4th, 2013

Como ya lo había anunciado, el martes pasado estuve dando una charla de aplicaciones distribuidas y Node.js, gracias a la gente de Node.js Argentina,  en el auditorio del Microsoft User Group de Argentina, en Buenos Aires.

Pueden ver y bajarse la presentación desde mi Skydrive

La idea fue mostrar algunos conceptos, y experimentos que estuve haciendo con Node.js, convirtiendo anteriores trabajos en otras tecnologías. Y mostrar código con ejemplos concretos.

Primero, expliqué lo que era una aplicación distribuida en el contexto de esta charla. Una aplicación distribuida es una aplicación que se ejecuta en varias computadoras, conectadas en red, que interactúan para resolver un problema. Ver http://en.wikipedia.org/wiki/Distributed_computing

Es decir, va más allá del clásico cliente servidor. Podemos tener varias computadoras para hacer web crawling de un sitio, o resolviendo la renderización de escenas de una película 3d. Las computadores que intervienen en el trabajo no necesariamente tienen el mismo software o programa: puede que algunas se ocupen solamente de algún paso del problema. Tampoco tienen que tener la misma plataforma o lenguaje de programación.

Lo que quise destacar, entonces, en la charla, son las facilidades que nos da Node.js y JavaScript para construir este tipo de aplicaciones. Ya en otras charlas afirmé “JavaScript es una manteca”, para destacar su flexibilidad. Y ahora, en esta charla, tuve la oportunidad de mostrar un tópico donde Node.js brilla: tanto por su soporte de red en los módulos “built-in”, como por su ecosistema, como por la filosofía de combinar módulos (como en Unix, ver Unix philosophy and Node.js de @izs)

Mencioné una entrevista a Alan Kay (ver su Dynabook)

I thought of objects being like biological cells and/or individual computers on a network, only able to communicate with messages

Until real software engineering is developed, the next best practice is to develop with a dynamic system that has extreme late binding in all aspects

The big idea is “messaging”

Es interensante que Kay mencionara células biológicas: nuestros nodos en ejecución pueden tomarse como células, que forman el organismo de nuestra aplicación distribuida. Como dice Kay, el gran tema es el “messaging”, el envío de mensajes entre las partes. Las aplicaciones distribuidas nos dan la oportunidad de olvidarnos del concepto de función/rutina a la que llamamos con parámetros y esperamos que termine de ejecutar para dar un resultado, y aún de una llamada con callback: un elemento de nuestra aplicación distribuida enviará un mensaje, desentendiéndose de obtener una respuesta.

También mencioné a Richard Feynman (algún post de mis enlaces), ver

http://boards.straightdope.com/sdmb/showthread.php?t=159936

Feynman was once asked by a Caltech faculty member to explain why spin 1/2 particles obey Fermi-Dirac statistics. He gauged his audience perfectly and said "I’ll prepare a freshman lecture on it." But a few days later he returned and said, "You know, I couldn’t do it. I couldn’t reduce it to the freshman level. That means we really don’t understand it."

Adaptando su frase a “si no lo podemos explicar, es que no lo entendemos” como motivación personal para dar charlas. Recordé su trabajo de estudio “por su cuenta” de la física cuántica según Feyman por Dyson, como justificación lejana a experimentar con un tema, en vez de tomar lo que ya está hecho directamente.

Pues lo que presenté luego, son experimentos sobre Node.js para aplicaciones distribuidas. Pero ¿por qué Node.js? En JavaScript, un mensaje puede ser un simple objeto serializable a JSON (un objeto sin ciclos, o sea, un árbol). Y para el transporte del mensaje podemos elegir multitud de módulos en el ecosistema de Node, como usar el require(‘net’) o require(‘http’) que vienen “built-it” en el núcleo de Node.js

Preguntas que tenemos que hacernos en cada caso de aplicación distribuida:

¿Qué elementos de nuestra aplicación producen mensajes?

¿Qué elementos consumen mensajes?

Un mensaje ¿es consumido por un solo elemento? ¿o puede ser procesado por varios elementos interesados?

Las máquinas y programas que ejecutan ¿están determinados desde el comienzo? ¿o pueden variar con el tiempo? Por ejemplo, me gustaría sumar a mi aplicación distribuida unas cuarenta máquinas que a la noche están ociosas. ¿Se puede hacer? ¿Necesitamos esta característica?

Un mensaje producido en un elemento de una máquina ¿se consume localmente? ¿o puede viajar a otra máquina? ¿quién decide eso? ¿el programador, el programa supervisor?

Y dado un mensaje que tiene que llegar a otra máquina ¿cómo llega? ¿con qué transporte?

Si un mensaje tiene que ser procesado remotamente ¿cómo se selecciona la máquina destino? ¿por programa? ¿por algún balanceo de carga?

Esas preguntas se contestarán diferente en cada experimento o ejemplo que tengamos.

Uno de los experimentos (repetido de distintas formas) es un web crawler, compuesto lógicamente (partes lógicas, luego a implementar de distinta forma según el ejemplo/experimento):

Cuando tengamos que recuperar las páginas de un sitio, primero enviamos una URL inicial a un elemento Resolver. Este elemento mantiene la lista de páginas ya visitadas. Si la URL es una página no procesada aún, se envía la URL a un elemento Downloader (elemento lógico que puede estar implementado en varias máquinas). Es el encargado de conseguir el contenido de la página. Luego le pasa ese dato al elemento Harvester, que extrae los enlaces que consigue encontrar en la nueva página. Los enlaces se envían al Resolver, que examina si corresponde o no procesar esas URLs.

Un módulo que escribí (no fue el primero, sino que surgió de refactor y extracción de otros casos de uso) es ObjectStream

https://github.com/ajlopez/ObjectStream
https://github.com/ajlopez/ObjectStream/tree/master/samples/broadcast

que me permite enviar un objeto JavaScript (serializable a JSON) a un Object Stream, un stream que recibe objetos. Este stream puede enviar ese objeto, ya serializado a texto, por otro stream. Y hay un Object Stream que toma esas líneas de texto y las reconstruye como objetos. Esto me permite usar, por ejemplo, un stream de socket para enviar objetos JavaScript de una máquina a otra. Vean en los enlaces de arriba el ejemplo de Broadcast que mostré en la charla.

Basado en ObjectStream, me animé luego a armar

https://github.com/ajlopez/SimpleMessages
https://github.com/ajlopez/SimpleMessages/tree/master/samples/Broadcast

Permite que dos procesos establezcan canales bidireccionales de envío de mensajes, que arrivan en cualquier momento. Desde el punto de vista del código, uno puede exponer un servidor (o varios) o crear clientes que se conectan a otros servidores. Pero luego de efectuada la conexión, el intercambio de mensajes es simétrico: cualquiera de las partes puede enviar un mensaje en cualquier momento. Ya con esto podemos entretenernos bastante, escribiendo aplicaciones distribudas basadas en mensajes.

Pero a veces, necesitamos más que enviar un simple mensaje. Por ejemplo, se nos puede presentar la necesidad de llamar a un objeto que está ejecutando en otra máquina. Podemos implementar un Remote Procedure Call. Lo hice en:

https://github.com/ajlopez/SimpleRemote

Basado en SimpleMessages, tanto el cliente como el servidor pueden exponer un objeto “hacia afuera”, y la otra parte lo puede invocar, como si fuera un objeto local. Solamente que como el retorno de la respuesta no es inmediato, el programador que llama al método agrega un callback para procesar la respuesta cuando ésta llegue.

Para alternativas pueden ver:

http://stackoverflow.com/questions/5010814/whats-the-best-way-to-make-one-node-js-server-talk-to-another
http://stackoverflow.com/questions/7986088/rpc-and-messagequeues-in-node-js
https://github.com/substack/dnode
https://github.com/Flotype/now
https://code.google.com/p/protobuf-for-node/
https://code.google.com/p/protobuf/
https://github.com/Frans-Willem/IPCNode

Vean dnode, cómo tienen clientes para distintos lenguajes. O vean también algo más agnóstico, http://en.wikipedia.org/wiki/JSON-RPC

Tuve un caso de uso donde necesitaba repartir mensajes, no solamente enviar un mensaje desde A hasta B. Entonces nació:

https://github.com/ajlopez/SimpleBroadcast
https://github.com/ajlopez/SimpleBroadcast/tree/master/samples/Broadcast

De esta manera, un cliente puede enviar un mensaje a un servidor, y éste repartirlo en los demas clientes conectados. Vean que el mensaje no se transmite al cliente que lo originó, sólo a los demás. Hasta puede haber una “estrella” de servidores, donde cada servidor atiende a sus clientes, y actúa como cliente de los otros servidores:

Esto permite la escalabilidad agregando servidores a la estrella. También tiene un concepto algo más sofisticado, el servidor repetidor (ver el código y tests). En este software tuve colaboración de Fernando Lores.

En otros casos de uso, en vez de enviar mensajes, necesité que los que iban a procesar mensajes los pidieran explícitamente. Como quería realizar todos estos experimentos en Node.js, sin depender de software externo, escribí:

https://github.com/ajlopez/SimpleQueue
https://github.com/ajlopez/SimpleQueue/tree/master/samples/DistributedProducerConsumer

Al principio, implementé una cola en memoria, local. Y luego la expuse hacia otras máquinas usando SimpleRemote.

Otro caso de uso con el que me encontré es: necesito publicar mensajes, pero no sé de antemano a quién le interesa. Es similar a los eventos de Node.js: uno emite un evento, pero no sabe quienes se suscribieron a ellos. Llevado eso a algo distribuido escribí:

https://github.com/ajlopez/SimpleBus
https://github.com/ajlopez/SimpleBus/tree/master/samples/Market

Tanto los que publican como los que se suscriben a mensajes pueden estar en máquinas distintas.

En el ejemplo de Market que mostré en la charla (ver el enlace de arriba) la suscripción a los mensajes se puede hacer dando un mensaje ejemplo: todos los mensajes que tengan las mismas propiedades que el ejemplo, serán tomados para procesar por el subscriptor. También puedo enviar un predicado, y notablemente, ese predicado puede “viajar” desde el suscriptor a la maquina que tiene el servidor de bus (que podrían ser varias máquinas en estrella usando SimpleBroadcast).

Muchos de estos casos de uso fueron motivados por implementaciones que tuve que escribir en otras tecnologías. El trabajo que más influyó es lo que hice cuando trabajé para @asehmi:

Ver Remember Fabriq.

Basado en su proyecto Fabriq, reescribí algo en AjFabriqNode:

https://github.com/ajlopez/AjFabriqNode
https://github.com/ajlopez/AjFabriqNode/tree/master/samples/WebCrawler

AjFabriq se basa en tener varios nodos ejecutándose, cada uno declara un árbol de procesadores de mensajes. En base al contenido del mensajem se determina qué procesador de mensaje puede atenderlo. Cada nodo se puede conectar a otro de la red, y entre varios se intercambian cuáles procesadores de mensajes tiene cada uno. Entonces, podemos tener un Web Crawler distribuido donde en un nodo tenemos el resolver, y en otros tenemos downloaders y harvesters.

Otros prefieren enviar los mensajes directamente a un elemento específico. Basado en la implementación de actores en Akka/Scala, ver:

http://doc.akka.io/docs/akka/snapshot/general/actor-systems.html
http://doc.akka.io/docs/akka/snapshot/general/actors.html
http://doc.akka.io/docs/akka/snapshot/general/addressing.html

implementé algo más simple:

https://github.com/ajlopez/SimpleActors
https://github.com/ajlopez/SimpleActors/tree/master/samples/DistributedWebCrawler

Pero vean que en Akka, un mensaje se envía en general a un actor, identificado por su dirección.

Hay un proyecto Java, Storm Project en:

http://storm-project.net/

donde se puede armar una topología con los elementos lógicos que van a recibir, procesar y emitir tuplas (lo que para esta charla es mensajes). Hay productores de mensajes, los Spout, y procesadores de mensajes, los Bolt. Luego cada elemento puede ejecutarse en varias máquinas. Así, podemos tener una topología de Web Crawler con Resolver, Downloader y Harvester. Pero luego poner 20 downloaders en 10 máquinas, y 5 harvesters en las mismas máquinas u otras.

Así que, ni lerdo ni perezoso, escribí algo simple en Node.js:

https://github.com/ajlopez/SimpleStorm
https://github.com/ajlopez/SimpleStorm/tree/master/samples/DistributedWebCrawler

Lo que ví en mis experimentos, es que muchas veces necesito levantar varias máquinas, indicarles qué hacer, que aplicaciones lógicas ejecutar (por ejemplo, el web crawler), y que puedan intercambiar mensajes entre ellos. Mostré:

https://github.com/ajlopez/MultiNodes
https://github.com/ajlopez/MultiNodes/tree/master/samples/collatz

Lo interesante es que un nuevo nodo que se incorpora a la red, puede ser instruido dinámicamente a ejecutar algo (como instalar y lanzar una nueva instancia del web crawler).

Dos ejemplos finales:

Una implementación de algoritmo genético distribuido:

https://github.com/ajlopez/SimpleGA
https://github.com/ajlopez/SimpleGA/tree/master/samples/tspdistr

Y un fractal que se puede calcular en el browser, o en un servidor Node.js/Express, solo o ayudado por nodos worker adicionales:

https://github.com/ajlopez/NodeSamples/tree/master/Fractal
https://github.com/ajlopez/NodeSamples/tree/master/Fractal/html
https://github.com/ajlopez/NodeSamples/tree/master/Fractal/server
https://github.com/ajlopez/NodeSamples/tree/master/Fractal/distributed

Al final, mencioné varias razones para investigar con aplicaciones distribuidas: desde lo interesante del tema, como lo práctico (para Big Data, cálculo distribuido y en paralelo, etc). Pero resalté que tenemos que seguir investigando sobre aplicaciones distribuidas e inteligencia artificial. Nuestro sistema nervioso funciona con varios nodos, surgiendo una aplicación distribuidas en neuronas (¿recuerdan a Alan Kay hablando de células con mensajes?)

Otro de los temas que me interesan es tener lenguajes dinámicos que puedan distribuirse fácilmente entre nodos distribuidos (de hecho, me gustó JavaScript con Node.js, porque me libera de implementar eso). Ver:

Lenguajes de Programación, Computación Distribuida, Inteligencia Artificial
Experimentos Distribuidos

Nos leemos!

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

Node.js, Charlas en Buenos Aires: Aplicaciones Distribuidas; Introducción a ZMQ

Wednesday, April 24th, 2013

La gente de Node.js Argentina prepara una nueva reunión para el próximo martes 30 de abril:

http://www.meetup.com/NodeJS-Argentina/events/112809892/

Revisen el horario, la idea era que fuera de 18:30 a 21hs en la zona de Congreso, Buenos Aires, cerca de subtes y multitud de colectivos.

Además de reunión, habrá dos charlas. Una de Fernando Alonso, sobre Introducción a ZMQ con Node, no tengo el temario en detalle. Y además, estaré dando otra charla, sobre uno de mis temas preferidos: aplicaciones distribuidas, en este caso con Node.js. Puede ver mis posts sobre aplicaciones distribuidas en general. Pero esta vez, trataré el tema desde Node.js, que me parece una plataforma excelente para experimentar y trabajar con este tipo de aplicaciones. Algo ya adelanté el año pasado en mi charla del Día del Programador:

Experimentos distribuidos

Ahí encontraran algunos enlaces sobre lo que estoy probando y armando. Algo más lateral, pero para explicar mi interés en el tema distribuido y su relación con otros temas que ven que trato frecuentemente por acá:

Lenguajes de Programación, Computación Distribuida, Inteligencia Artificial

Espero poder transmitir algo de todo esto en la charla del Node.js meetup. Recuerden de revisar la página del grupo, que se vienen más reuniones con otros temas (por ejemplo, la anterior fue sobre Node.js y Raspberry Pi).

Nos leemos!

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

Node.Js en UDA Developers Challenge 2012

Wednesday, October 24th, 2012

Estoy preparando todo para viajar a Ecuador, la semana que viene. La gente de la Universidad de Azuay me invitó a dar un seminario sobre Node.js, Socket.io y programación real-time, como parte del UDA Developers Challenge 2012. Más información en:

http://www.uazuay.edu.ec/udadev/

Leo ahí:

UDA Developers Challenge 2012 es organizado por la Universidad del Azuay, como parte de su aporte a la comunidad, con el ánimo de convertirse en inpulsador de eventos anuales en el que se traten temas tecnológicos de actualidad; con el objetivo de fomentar la innovación y la madurez de nuevas tecnologías en el país. Brindando de esta manera una actualización continua a estudiantes y profesionales de esta área. La primera parte del evento consiste en el aprendizaje de estas nuevas tecnologías mediante seminarios/taller, y en una segunda parte se pondrán a prueba los conocimientos adquiridos mediante el concurso UDA Developers Challenge. Con el objetivo de tratar temas tecnológicos de actualidad, el tema seleccionado para el UDA Developers Challenge 2012 son las aplicaciones web en tiempo real. En el país se ha podido constatar el aumento significativo de teléfonos inteligentes (smartphones) y tablets, debido al gran número de funcionalidades que estos ofrecen mediante la diversidad de aplicaciones disponibles; lo que ha llevado a la concentración de las actividades alrededor de estos dispositivos móviles que día a día son más indispensables en el que hacer diario. Considerando este hecho y el naciente desarrollo de aplicaciones para móviles en el Ecuador, el tema que será tratado por el UDA Developers Challenge 2012, serán las aplicaciones en tiempo real. El evento se realizará los días 29, 30 y 31 de Octubre de 2012 y comenzará con los seminarios/taller para el desarrollo de aplicaciones en tiempo real, para esto se usara bases de datos no relacionales, NodeJS y HTML5; con una duración de 1 día por cada tema.

Mi aporte es en el segundo día de la primera parte. El gran tema: Node.js, desde cero, para gente que sabe programar pero que quiere iniciarse en Node.js para participar del concurso de la segunda parte. Mi intención es mostrar: Node.js desde el principio, programación asincrónica, manejo de paquetes con NPM, algo de tests (usando TDD, módulo assert, módulo nodeunit), usar el módulo http para primeros ejemplos de web, puede que agregue módulo TCP para algún ejemplo con nodos distribuidos. Luego pasar a algún ejemplo simple de Express (páginas web, MVC). Terminado eso, pasaremos a ver algunos ejemplos simples de Socket.IO, para comenzar a entender cómo permite este módulo implementar aplicaciones que reaccionan en tiempo real, y relacionando varios usuarios. Aparecerá el clásico ejemplo de chat y algún ejemplo simple de juego multiusuario (usando un canvas de HTML5).

Para mí, será el primer viaje a Ecuador, y me encuentro muy entusiasmado preparando los temas de este seminario. Los ejemplos sencillos van quedando principalmente en:

https://github.com/ajlopez/NodeSamples

(estoy actualizando los ejemplos simples para las nuevas versiones de Express y Socket.IO). Seguramente usaré otros repositorios con ejemplos más completos, por ejemplo los propios “samples” de Express y Socket.io. Para el tema distribuido, reusaré lo que mostré aquí en Buenos Aires para el día del programador, por ejemplo, el algoritmo genético distribuido, que usa Socket.IO para comunicar browser y servidor node, y tcp para comunicar nodos node de trabajo. En cuanto pueda, repito los temas por acá, en Argentina.

Espero encontrarme con desarrolladores en Ecuador, a los que conozco sólo por las listas de correo. Y conocer los Andes, en la ciudad de Cuenca, donde está la sede donde se dicta esta primera parte de tres días de UDA Dev 2012.

Gracias a @gringotuc y a @martinsalias que me pusiero en contacto con Ramiro, desarrollador ecuatoriano, estudiante en Buenos Aires, para tener esta gran oportunidad. Y a Marcos, que desde Ecuador está organizando mi viaje.

Nos leemos!

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

AjFabriq en NodeJs (Parte 3) Una Aplicación Distribuida Simple

Thursday, September 15th, 2011

Anterior Post

Ejecutemos nuestra “killer app” (un simple contador) en dos nodos. En el repositorio, en examples\numbers, hay un programa appserver.js:

Es similar a mi ejemplo local. La diferencia es que el procesador de mensajes principal escucha por una puerta:

/**
 * Host.
 */
var host = ajfabriq.createLocalHost();
/**
 * Application configuration.
 */
 
var app = host.createProcessor('numbers', 'application');
var node = app.createProcessor('processor', 'node');
node.on('decrement', function (message) {
	console.log("Processing number " + message.number);
	
	if (message.number <= 1) {
		console.log("End Processing");
		return;
		}
		
	var number = message.number-1;
	
	this.post({ action: 'decrement', number: number });
});
host.listen(3000);
host.process({ application: 'numbers', node: 'processor', action: 'decrement', number: 10 });

En este código estoy usando ajfabriq.createLocalHost() en vez de .createProcessor(). Y host.listen(3000) comienza a aceptar mensajes desde otros nodos.

Ejecuto otro programa: appclient.js. Tiene los mismos procesadores locales:

/**
 * Application configuration.
 */
 
var app = host.createProcessor('numbers', 'application');
var node = app.createProcessor('processor', 'node');
node.on('decrement', function (message) {
	console.log("Processing number " + message.number);
	if (message.number <= 1)
		return;
		
	var number = message.number-1;
	
	this.post({ action: 'decrement', number: number });
});

Pero se conecta con el primer server y envía un nuevo mensaje:

var socket = new net.Socket();
socket.connect(3000, 'localhost',
	function() {
		host.connect(new ajfabriq.Channel(socket), true);
		socket.write(JSON.stringify({name : 'ajfmessage', message: { application: 'numbers', node: 'processor', action: 'decrement', number: 10 }}));
	}
);
	

ajfabriq.Channel es el canal bidireccional entre dos servidores ajfabriq.

Esta es la salida del segundo servidor:

Noten el intercambio de mensajes entre los dos servidores, al comienzo. Estan informando de sus procesadores de mensajes locales al otro servidor. De esta forma, cada servidor sabe qué mensajes puede procesar otro nodo.

Esta es la actividad del primer servidor luego del mensaje enviado por el segundo servidor:

Algunos de los números son procesados por el segundo servidor, y otros son ruteados al primer servidor. El ruteo es una simple elección al azar. Los objetos LocalHost tiene un nuevo método .post:

LocalHost.prototype.post = function (message) {
	var hosts = [ this ];
	
	for (var remote in this.remotes) {
		if (this.remotes[remote].accepts(message)) {
			hosts.push(this.remotes[remote]);
		}
	}
	var n = Math.floor(Math.random() * hosts.length);
	
	hosts[n].process(message);
};

Próximos pasos: un mejor ruteo, mejorar la comunicación de sockets (debo manejar mensajes JSON grandes, que pueden venir en varias comunicaciones, no en un solo read), logueo, más ejemplos de aplicaciones, ejemplos con más de dos nodos.

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

AjFabriq en NodeJs (Parte 2) Una aplicación local simple

Wednesday, September 14th, 2011

Anterior Post 
Siguiente Post

Veamos de explorar cómo usar AjFabriq en NodeJs. Hay una simple aplicación:

https://github.com/ajlopez/AjFabriqJs/tree/master/examples/numbers

Implementa la última “killer application”: recibe un mensaje con un número, y postea un mensaje con ese número decrementado en uno ;-). Veamos có se define la aplicación:

/**
 * Module dependencies.
 */
 
var ajf = require('ajfabriq');

 

 

Incluí al directorio c:\Git en mi variable de ambiente NODE_PATH, y hay ahí un c:\Git\ajfabriq conteniendo mi repositorio git local de lo que estoy desarrollando. Pueden clonar el repo en el directorio node_modules donde está el NodeJs 5.x (see Playing With NodeJs (1) Running on Windows (and Azure), Jugando con NodeJs (1) En Windows (y en Azure)) .

AjFabriq define un objeto que expone algunos métodos. Esta es la manera de crear un procesador de mensajes que es local, y éste no es expuesto a otros servidor (en el próximo post explicaré una aplicación distribuida):

/**
 * Host.
 */
var host = ajf.createProcessor();

 

 

El procesador de mensajes (ver anterior post) puede contener otros procesadores, es un “composite”. El método aprocessor.createProcessor crea un nuevo procesador y lo agrega a su procesador padre:

/**
 * Application configuration.
 */
 
var app = host.createProcessor('numbers', 'application');
var node = app.createProcessor('processor', 'node');

 

 

El primer procesador, en la variable app, aceptará y procesará mensajes con la propiedad “application” teniendo como valor a “numbers”. Su procesador hijo procesará mensajes con la propiedad “node” con valor “processor”. De esta forma, podemos definir un árbol de procesadores de mensajes. Las propiedades del mensajes y sus valores forman entonces su información de ruteo, así que cada mensaje será enviado al procesador apropiado.

Pero ¿cómo definir la conducta del procesador hijo final? Para estar alineado con el procesamiento asincrónico de NodeJs, cada procesador hereda de un EventEmitter. Desde el anterior post, definí al Processor como una “subclase” de process.EventEmitter en el código de AjFabriq:

var EventEmitter = process.EventEmitter;
// ...
function Processor(name, kind)
{
	this.name = name;
	this.kind = kind;
	this.processors = [];
}
Processor.prototype.__proto__ = EventEmitter.prototype;

 

 

Ahora, podemos definir el procesador hijo final:

node.on('decrement', function (message) {
	console.log("Processing number " + message.number);
	
	if (message.number <= 1) {
		console.log("End Processing");
		return;
		}
		
	var number = message.number-1;
	
	this.post({ action: 'decrement', number: number });
});

 

 

El procesamiento de mensajes detecta una propiedad llamada “action”, y dispara el correspondiente evento. Noten el método emit en este código de AjFabriq:

Processor.prototype.process = function (message)
{
	if (this.processors == null || this.processors.length == 0) {
		this.emit(message.action, message);
		return;
	}
	
	for (var processor in this.processors)
		if (this.processors[processor].accepts(message)) 
		{
			this.processors[processor].process(message);
		}
}

 

 

 

Al final de mi “killer app”, un mensaje es enviado al procesador inicial:

host.process({ application: 'numbers', node: 'processor', action: 'decrement', number: 10 });

 

 

La salida:

Pero, esperen! ¿vieron el código de ‘decrement’ que mostré más arriba? Hay un:

this.post({ action: 'decrement', number: number });

 

 

No hay propiedad aplication, ni node. Y funciona igual. Si uno postea un mensaje a un procesador (en este caso al que está en la variable node), los procesadores padres llena las propiedades faltantes. Así, la propiedad application toma el valor “numbers”, y la propiedad node toma el valor de “processor”. Si quieren enviar un mensaje a otra aplicación, podemos poner explícitamente la propiedad correspondiente en el nuevo mensaje a enviar. Noten que la práctica recomendada es: no cambien el mensaje original. Puede que sea procesado por otros procesadores.

Para futuros posts: nuevas aplicaciones, un ejemplo distribuido

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com
http://twitter.com/ajlopez

Ejecutando AjSharp en Azure

Tuesday, June 14th, 2011

El code kata de este pasado fin de semana fue algo que estaba pensando desde el último año: ejecutar AjSharp (mis post en español de AjSharp) dentro de un Worker Role de Azure. Pero desde antes que pienso: un intérprete como AjSharp puede servir de lenguaje de scripting en sistemas distribuidos. Esta incursión en Azure es una prueba de concepto interesante.

La idea es: una instancia de worker role recibe un texto via una cola de mensaje. El texto contiene código AjSharp y lo ejecuta. La salida (digamos, los PrintLine) se captura como texto y se envía como mensaje a otra cola.

El resultado del ejercicio está dentro de mi AjCodeKata project: tienen que bajarse trunk\Azure\AzureAjSharp Y TAMBIEN trunk\AjLanguage (donde está el proyecto AjSharp).

La solución:

Los proyectos:

AzureAjSharp.WorkerRole: un worker role de ejemplo, con estas líneas agregadas:

CloudStorageAccount account = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
Processor processor = new Processor(account);
processor.Start();

Azure.AjSharp: la librería de clases principal del proyecto. Contiene una clase Processor. Los constructores necesitan una cuenta de cloud y los nombres (opcionales, hay valores “default”): cola de requests, responses y un blob container. La cola de request contiene mensajes con código AjSharp para ejecutar (recuerden que AjSharp puede acceder a clases y objetos .NET: pueden invocar código compilado tranquilamente). La cola de response tiene el texto de salida de esas ejecuciones. El código de arriba processor.Start() inicia la lectura y ejecución de esos mensajes AjSharp.

AzureAjSharp.Console: Es el programa que lee líneas de la consola, y cuando ingresamos una línea que contiene sólo “send”, el texto ingresado se convierte en un mensaje Azure que va a la cola de requests. Este programa también va leyendo (en un Thread aparte) los mensajes que le llegan por la cola de responses, imprimiendo el resultado.

AzureLibrary: Clases auxiliares que usé en otros ejemplos de Azure.

AjSharpVS2010, AjLanguageVS2010: Implementación de AjSharp .

Cuando ejecuto el programa de consola, puedo enviar código AjSharp para ejecutar en un worker role, y recibir el resultado:

Vean que uso clases .NET como DirectoryInfo.

Y hay más: AjSharp soporta el Include(“nombredearchivoaserincluido”); donde el archivo contiene más código AjSharp. Modifiqué el lanzamiento de la máquina AjSharp para que tenga una versión cambiada de Include: ahora busca el contenido en un blob. Eso permite incluir y reusar código que no quepa en un mensaje, desde un blob container

Un gráfico:

Entonces, subí algo de código (los archivos originales están en el directorio Examples del proyecto Azure.AjSharp) en el contenedor blob llamado ajsfiles (para esta prueba en mi DevStorage):

(Estoy usando Neudesic Azure Storage Explorer, pero podría usar también CloudBerry Explorer for Azure Storage: soporta el manejo de carpetas en árbol).

Esta es el resultado de la ejecución de código con include de HelloWorld.ajs, y ForOneToTen.ajs:

Próximos pasos:

– Escribir más código utilitario en AjSharp, para ser incluido en otros programas, como: utilitarios de manejo de File y Directory, download y upload de blobs, envío y recepción de mensajes en cola, mensajes a todos los worker role intances, bajada y carga de assemblies, objetos a compartir entre request y request de AjSharp, etc. El cielo es el límite! 😉

Entonces, podemos (nosotros o un programa) enviar tareas dinámicamente y recibir resultados. Algo para tener: Guids para identificar tareas y sus resultados; una interfaz web; resultados almacenados como blobs; cache (y flush) de los archivos incluidos, etc…

Nos leemos!

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




				

Azure: Una aplicación Fractal

Wednesday, February 16th, 2011

En enero pasado, reimplementé mi aplicación Fractal, ahora usando Azure (mis posts sobre Azure). La idea es calcular cada sector de una imagen de un fractal, usando el poder de los worker roles, almacenar el resultado en blobs, y consumirlos desde una aplicación WinForm.

Esta es la solución:

El código está en mi projecto AjCodeKatas, en:

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

Si quieren, tiene directamente el código congelado a ahora en: AzureFractal.zip.

Los proyectos en la solución:

AzureFractal: la definiciones para Azure (modelo de servicio, configuración).

Fractal: contiene mi código original de mi anterior aplicación fractal. Es un proyecto de librería de clases.

Fractal.Azure: algunos utilitarios de serialización, un servicio fachada para enviar un mensaje a la cola Azure.

AzureLibrary: clases utilitarias que he usado en otros ejemplos Azure. Están evolucionando en cada ejemplo.

FractalWorkerRole: el Worker Role que consumen mensajes de una cola, que indican el sector (un rectángulo) del fractal de Mandelbrot a calcular.

Fractal.GUI: un cliente WinForm que envía y recibe mensajes a/desde colas usadas en el Worker Role.

Deberían configurar la solución para tener dos proyectos a lanzar:

La aplicación WinForm envía un mensaje a una cola, con la información del sector a calcular:

private void Calculate()
{
    Bitmap bitmap = new Bitmap(pcbFractal.Width, 
       pcbFractal.Height);
    pcbFractal.Image = bitmap;
    pcbFractal.Refresh();
    realWidth = realDelta * pcbFractal.Width;
    imgHeight = imgDelta * pcbFractal.Height;
    realMin = realCenter - realWidth / 2;
    imgMin = imgCenter - imgHeight / 2;
    int width = pcbFractal.Width;
    int height = pcbFractal.Height;
    Guid id = Guid.NewGuid();
    SectorInfo sectorinfo = new SectorInfo()
    {
        Id = id,
        FromX = 0,
        FromY = 0,
        Width = width,
        Height = height,
        RealMinimum = realMin,
        ImgMinimum = imgMin,
        Delta = realDelta,
        MaxIterations = colors.Length,
        MaxValue = 4
    };
    Calculator calculator = new Calculator();
    this.queue.AddMessage(
        SectorUtilities.FromSectorInfoToMessage(sectorinfo));
}

El Worker Role lee mensajes desde una cola, y la deserializa en SectorInfo:

while (true)
{
    CloudQueueMessage msg = queue.GetMessage();
    if (msg != null)
    {
        Trace.WriteLine(string.Format("Processing {0}", msg.AsString));
        SectorInfo info = SectorUtilities.FromMessageToSectorInfo(msg);

Si el sector es muy grande, nuevos mensajes son generados:

if (info.Width > 100 || info.Height > 100)
{
    Trace.WriteLine("Splitting message...");
    for (int x = 0; x < info.Width; x += 100)
        for (int y = 0; y < info.Height; y += 100)
        {
            SectorInfo newinfo = info.Clone();
            newinfo.FromX = x + info.FromX;
            newinfo.FromY = y + info.FromY;
            newinfo.Width = Math.Min(100, info.Width - x);
            newinfo.Height = Math.Min(100, info.Height - y);
            CloudQueueMessage newmsg = 
              SectorUtilities.FromSectorInfoToMessage(newinfo);
            queue.AddMessage(newmsg);
        }
}

Si el sector tiene un tamaño tratable, es procesado:

Trace.WriteLine("Processing message...");
Sector sector = calculator.CalculateSector(info);
string blobname = string.Format("{0}.{1}.{2}.{3}.{4}", 
info.Id, sector.FromX, sector.FromY, sector.Width, sector.Height);
CloudBlob blob = blobContainer.GetBlobReference(blobname);
MemoryStream stream = new MemoryStream();
BinaryWriter writer =new BinaryWriter(stream);
foreach (int value in sector.Values)
    writer.Write(value);
writer.Flush();
stream.Seek(0, SeekOrigin.Begin);
blob.UploadFromStream(stream);
stream.Close();
CloudQueueMessage outmsg = new CloudQueueMessage(blobname);
outqueue.AddMessage(outmsg);

Un blob con el resultado es generado, y un mensaje es enviado a otra cola para notificar a la aplicación cliente.

El WinForm tiene un thread con un ciclo leyendo mensajes desde una segunda cola:

string blobname = msg.AsString;
CloudBlob blob = this.blobContainer.GetBlobReference(blobname);
MemoryStream stream = new MemoryStream();
blob.DownloadToStream(stream);
blob.Delete();
this.inqueue.DeleteMessage(msg);
string[] parameters = blobname.Split('.');
Guid id = new Guid(parameters[0]);
int fromx = Int32.Parse(parameters[1]);
int fromy = Int32.Parse(parameters[2]);
int width = Int32.Parse(parameters[3]);
int height = Int32.Parse(parameters[4]);
int[] values = new int[width * height];
stream.Seek(0, SeekOrigin.Begin);
BinaryReader reader = new BinaryReader(stream);
for (int k = 0; k < values.Length; k++)
    values[k] = reader.ReadInt32();
stream.Close();
this.Invoke((Action<int,int,int,int,int[]>) ((x,y,h,w,v) 
=> 
this.DrawValues(x,y,h,w,v)), fromx, fromy, width, height, values);

Notel el uso de .Invoke para ejecutar el dibujo del sector dentro del thread de UI (User Interface).

Esta es la aplicación WinForm, luego de hacer click en el botón Calculate. Noten que los sectores están arrivando:

Hay sectores que todavía no llegaron. Podemos arrastrar el mouse y soltarlo para marcar un nuevo sector:

Podemos cambiar los colores, con el botón New Colors:

Esta es una aplicación de ejemplo, una prueba de concepto. Probablemente, tengamos un mejor rendimiento usando una máquina simple. Pero la idea es que podemos dar trabajo a Worker Roles, especialmente si el trabajo puede hacerse en paralelo (imaginen una máquina para render en paralelo de animaciones). Si Uds. usan esta aplicación en Azure, con varias instancias de Worker Role, el rendimiento podría mejorar.

Próximos pasos: implementar un Web Crawler distribuido, intentar un algoritmo genético distribuido, todo usando la nube Azure.

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

Azure: Una aplicación simple usando Tables

Wednesday, February 9th, 2011

Continuando con mis ejemplos de Azure, esta vez escribí una simple aplicación web CRUD, usando Tables, con Tables, usando Azure Storage Client.

Es una aplicación de ASP.NET clásico, con esta vista para CustomerList.aspx:

Pueden bajarse la solución desde mi AjCodeKatas Google project. El código está en:

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

Si quieren pueden bajarse directamente la versión “congelada” desde: AzureCustomers.zip.

La simple entidad Customer:

public class Customer : TableServiceEntity
{
    public Customer()
        : this(Guid.NewGuid().ToString())
    {
    }
    public Customer(string id)
        : base(id, string.Empty)
    {
    }
    public string Name { get; set; }
    public string Address { get; set; }
    public string Notes { get; set; }
}

Estoy usando la PartitionKey como clave primaria, llenándola con un Guid. La RowKey es el string vacío. En una aplicación menos simple, podría grabar las facturas de un cliente usando la misma Partition Key, identificando cada factura con un RowKey distinto.

Un DataContext está a cargo de exponer un IQueryable de Customers:

public class DataContext : TableServiceContext
{
    public const string CustomerTableName = "Customers";
    public DataContext(string baseAddress, StorageCredentials credentials)
        : base(baseAddress, credentials)
    {
        this.IgnoreResourceNotFoundException = true;
    }
    public DataContext(CloudStorageAccount storageAccount)
        : base(storageAccount.TableEndpoint.AbsoluteUri, storageAccount.Credentials)
    {
        this.IgnoreResourceNotFoundException = true;
    }       
    public IQueryable<Customer> Customers
    {
        get
        {
            return this.CreateQuery<Customer>(CustomerTableName);
        }
    }
}

Noten el IgnoreNotFoundException: si está en verdadero, puedo recuperar un cliente inexistente sin levantar una excepción, y retornar un valor null.

Hay un servicio para acceder y manejar los Customers:

public class CustomerServices
{
    private DataContext context;
    public CustomerServices(DataContext context)
    {
        this.context = context;
    }
    public Customer GetCustomerById(string id)
    {
        return this.context.Customers.Where(c => c.PartitionKey == id).SingleOrDefault();
    }
    public IEnumerable<Customer> GetCustomerList()
    {
        return this.context.Customers.ToList().OrderBy(c => c.Name);
    }
    public void AddCustomer(Customer customer)
    {
        this.context.AddObject(DataContext.CustomerTableName, customer);
        this.context.SaveChanges();
    }
    public void UpdateCustomer(Customer customer)
    {
        this.context.AttachTo(DataContext.CustomerTableName, customer, "*");
        this.context.UpdateObject(customer);
        this.context.SaveChanges();
    }
    public void DeleteCustomerById(string id)
    {
        Customer c = this.GetCustomerById(id);
        this.context.DeleteObject(c);
        this.context.SaveChanges();
    }
}

Noten el uso de Attach con ETag (tercer parámetro) de “*” (any). De esta forma, podemos actualizar el cliente adosando el “creado en memoria” al contexto de datos, sin recuperalo desde la base de datos. Esta forma de hacerlo es viable si tengo todos los datos del cliente, y no me importa sobreescribir cambios posibles que se hubieran hecho en el storage. En muchas aplicaciones uno cambia solamente parte del estado, ante una operación (por ejemplo, cambio de domiciolio). Entonces se recupera el objeto, se cambia parte del estado y se lo graba.

Usando el servico para recuperar los clientes:

CloudStorageAccount storage = CloudStorageAccount.FromConfigurationSetting("DataConnectionString");
CustomerServices services = new CustomerServices(new DataContext(storage));
this.grdCustomerList.DataSource = services.GetCustomerList();
this.grdCustomerList.DataBind();

Nota: ésta es una aplicación de ejemplo, simple y directa. Una aplicación real debería separar el modelo de vista del modelo de negocio, y posiblemente, usar ASP.NET MVC en la presentación. Escribiré este ejemplo usando MVC. En otra serie (fuera de ésta relacionado con Azura), quiero escribir una aplicación ASP.NET MVC usando TDD.

Próximos pasos en Azure: una aplicación distribuida que calcule un fractar, un web crawler distribuido, un algoritmo genético usando Worker Roles.

Nos leemos!

Angel “Java” Lopez

http://www.ajlopez.com

http://twitter.com/ajlopez

Programando con Windows Azure en Buenos Aires

Thursday, February 3rd, 2011

Gracias a la gente del MUG (Microsoft User Group) de Argentina, el martes 15 y el jueves 17 de Febrero estaré dando un curso gratuito de programación en Windows Azure. Son dos horas el martes y dos horas más el jueves, de 19 a 21hs.

Detalles e inscripción (hay que registrarse) en:

Seminario Gratuito – Programando en Windows Azure

Los temas a dar:

– Cloud Computing en general, IaaS , PaaS, SaaS
– Windows Azure
– Conceptos del HyperVisor, Fabric
– Service Model
– Web Roles
– Worker Roles
– Azure Storage: Blobs, Queues, Tables
– Patrones
– Ejemplos

Voy a mostrar ejemplos, algunos ya publicados acá en posts sobre Azure, y otros nuevos. Azure me parece un tema muy interesante, que permite comenzar a implementar aplicaciones distribuidas, más allá de tener las ventajas del Cloud Computing (escalabilidad, disponibilidad…) Habrán notado que desde hace años aparecen por este blog posts relacionados con aplicaciones distribuidas. Y los que me escucharon en alguna charla (como las de Maratón 2.0) saben que me decanto por explotar el tema de distribución para implementar temas nuevos, como la convergencia de inteligencia artifical y web semántica, y más.

Espero que los que puedan venir encuentren interesante el seminario. Como siempre, quedará publicado por acá el material presentado.

Nos leemos!

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