La inmensa aceleración con la que se mueven las tendencias tecnológicas, y la cada vez mayor necesidad de incluir elementos de caracter colaborativo en el desarrollo web, están provocando el exponencial avance en el nivel de abstracción y disminución de la complejidad de las herramientas para trabajar con elementos de red en tiempo real. Lo que ayer fue la implementación desde cero de un Socket, o el apoyo en mecanismos tales como RMI(Invocación Remota de Métodos) y CORBA(Arquitectura Común de Intermediarios en Peticiones a Objetos), hoy en día se pueden realizar con un par de líneas de código – literalmente-. En este artículo, examinaremos como con el marco de trabajo de Rails y la gema de Juggenaut se puede lograr la implementación de un prototipo sencillo de chat, con relativamente poco esfuerzo.
Introducción a la gema de Juggernaut 2
Juggernaut 2, tal como lo define su creador en [1], es una gema para Ruby on Rails que permite enviar datos a un navegador que actúa como cliente, abriendo espacios para la creación de juegos multi-jugador, chats y en general colaboración de red en tiempo real. Para su versión 2, Juggernaut se apoya en node.js, por lo cual es rápido, escalable y con soporte para millones de usuarios de forma concurrente. El flujo de transmisión de Juggernaut se puede evidenciar con el siguiente diagrama:
Instalación
Requerimientos
- Node.js
- Redis
- Ruby
Instalación de Juggernaut
- Instalar node.js, se puede encontrar información sobre su instalación y los archivos fuentes en http://nodejs.org/
- Instalar redis, se pueden encontrar información sobre su instalación y los archivos fuentes en http://code.google.com/p/redis/
- Instalación y descarga de la gema de Juggernaut y su aplicativo, mediante:
git clone git://github.com/maccman/juggernaut.git --recursive
gem install juggernaut --pre
Implementación de un sencillo chat
Para probar de forma sencilla Juggernaut 2, realizaremos un pequeño cliente chat alojado en una aplicación de Rails que permita una comunicación entre varios usuarios. El mockup diseñado, fue el siguiente:
Para comprender la arquitectura global, en la que se basará el ejemplo, se diseño el siguiente diagrama de despliegue:
Tal como se puede apreciar en el diagrama, la ida centra gira en torno a una arquitectura Cliente-Servidor. Para ello, el servidor de la aplicación de chat expone sus funcionalidades a través del servidor WebRick por el puerto 3000, las cuales son consumidas por n clientes en espacios de tiempo a través de la conexión de los exploradores web.
Del lado del servidor, el coordinador central sera la aplicación de chat quien por medio de la inclusión del archivo «application.js» conectará con el servidor de Juggernaut, que a su vez utiliza NodejJs y Redis. Finalmente por medio de la gema de Juggernaut anexada a la aplicación se enviaran los mensajes que pueden ser leidos en tiempo real por cada uno de los clientes conectados. Veamos un poco de código:
La vista
<script src="http://localhost:8080/application.js" type="text/javascript" charset="utf-8"></script> <%= javascript_include_tag "prototype" %> <textarea id="log" readonly></textarea> <script type="text/javascript" charset="utf-8"> var logElement = document.getElementById("log"); logElement.value = ""; var log = function(data){ logElement.value += (data + "\n"); }; var jug = new Juggernaut('localhost'); jug.on("connect", function(){ log("Connected") }); jug.on("disconnect", function(){ log("Disconnected") }); jug.on("reconnect", function(){ log("Reconnecting") }); log("Subscribing to channel1"); jug.subscribe("channel1", function(data){ log("Got data: " + data); }); // Expose for debugging window.jug = jug; </script> <% form_remote_tag(:url => {:action => 'send_m'}, :success => "document.getElementById('msg_body').value = ''") do %> <%= text_field_tag 'msg_body', '', :size => '50' %> <input type="submit" value="Send Message" name="commit"></input> <% end %>
Lo primero para considerar, es la inclusión de el javaScript alojado en localhost en el puerto 8080. Esto se realiza puesto que al iniciar Juggernaut, este se encuentra escuchando en dicho puerto. Así por medio de la inclusión del JavaScript enlazamos nuestra aplicación de prueba con Juggernaut. Lo siguiente es el código JavaScript necesario para iniciar las conexiones, abrir el canal de suscripción y la manipulación del textarea de nombre log, para colocar allí los mensajes. Por último, se utiliza un formulario manejado de forma remota para por medio de AJAX ir mostrando en el textarea los mensajes enviados.
El controlador
require 'juggernaut' class ChatController < ApplicationController def index end def send_m Juggernaut.publish('channel1',params[:msg_body]) redirect_to :action => 'index' end end
Puesta en marcha
Para poner en marcha el ejemplo, se deben seguir los siguientes pasos:
- Copiar el archivo «WebSocketMain.swf» de la carpeta del servidor Juggernaut obtenida de git a la carpeta pública de la aplicación de chat.
- Iniciar Redis
./redis-server redis.conf
- Ir a la carpeta del servidor Juggernaut y ponerlo en marcha:
node server.js
- Iniciar nuestra aplicación de ejemplo
script/server
Descargar código fuente del ejemplo
Consideraciones finales
- Para colocar Juggernaut en producción, es necesario cambiar localhost por la dirección ip de la máquina, una buena alternativa es usando archivos de configuración.
- Se puede ampliar esta información en [1] con ejemplos mas avanzados y de diversa índole o visitando el grupo de google de Juggernaut en [2]
Referencias y enlaces de interés
[1] https://github.com/maccman/juggernaut
[2]http://groups.google.com/group/Juggernaut-for-Rails/?pli=1