j Groups

10
SISTEMAS DISTRIBUIDOS 1 Fecha: Noviembre 11, 2013 Tema: JGroups Soporte para Comunicación a Grupos 1. Objetivos Describir los principios de funcionamiento de la comunicación en grupos basada en el uso de JGroups. Establecer la relación existente entre este mecanismo de comunicación grupal y los sistemas distribuidos. 2. Introducción JGroups es un conjunto de herramientas (toolkit) para la comunicación confiable en grupo, escrito en Java. Es parte de la serie de herramientas de comunicación grupal que emergieron de la Universidad de Cornell, basándose en los conceptos fundamentales desarrollados en ISIS, Horus y Ensemble. Actualmente es mantenido y desarrollado por la comunidad open source JGroups, parte de la comunidad JBoss. Motivación de Desarrollo Se buscó la creación de una tecnología de soporte para aplicaciones confiables orientadas a objetos que presente este mismo paradigma. Se empleó el acercamiento toolkit para lograr la confiabilidad, debido a la posibilidad de proveer un número de clases con diferentes niveles de abstracción, que puedan corresponder a los variantes requerimientos de las aplicaciones (sin imponer un modelo específico). Su primera versión empleaba los protocolos de comunicación grupal provistos por Ensemble (escrito en C), representado una interfaz Java modelada para y en base a dicha herramienta. Se eligió aprovechar las características del lenguaje Java: la portabilidad al poder ejecutarse en distintas arquitecturas y la posibilidad de generar instancias en tiempo de ejecución (aplicado, por ejemplo, para generar todo el stack de protocolos en runtime). 3. Marco Teórico

Transcript of j Groups

Page 1: j Groups

SISTEMAS DISTRIBUIDOS

1

Fecha: Noviembre 11, 2013

Tema: JGroups – Soporte para Comunicación a Grupos

1. Objetivos

Describir los principios de funcionamiento de la comunicación en grupos basada en el uso de JGroups.

Establecer la relación existente entre este mecanismo de comunicación grupal y los sistemas distribuidos. 2. Introducción

JGroups es un conjunto de herramientas (toolkit) para la comunicación confiable en grupo, escrito en Java. Es parte de la serie de herramientas de comunicación grupal que emergieron de la Universidad de Cornell, basándose en los conceptos fundamentales desarrollados en ISIS, Horus y Ensemble. Actualmente es mantenido y desarrollado por la comunidad open source JGroups, parte de la comunidad JBoss.

Motivación de Desarrollo

Se buscó la creación de una tecnología de soporte para aplicaciones confiables orientadas a objetos que presente este mismo paradigma. Se empleó el acercamiento toolkit para lograr la confiabilidad, debido a la posibilidad de proveer un número de clases con diferentes niveles de abstracción, que puedan corresponder a los variantes requerimientos de las aplicaciones (sin imponer un modelo específico). Su primera versión empleaba los protocolos de comunicación grupal provistos por Ensemble (escrito en C), representado una interfaz Java modelada para y en base a dicha herramienta. Se eligió aprovechar las características del lenguaje Java: la portabilidad al poder ejecutarse en distintas arquitecturas y la posibilidad de generar instancias en tiempo de ejecución (aplicado, por ejemplo, para generar todo el stack de protocolos en runtime).

3. Marco Teórico

Page 2: j Groups

2

Comunicación Indirecta

Comunicación indirecta se define como la comunicación establecida entre entidades en un sistema distribuido mediante un intermediario, sin acoplamiento directo entre la entidad que realiza el envío y el receptor (o receptores). La naturaleza precisa del intermediario varía en cada estrategia específica de implementación.

Comunicación en Grupo

La comunicación en grupo ofrece un servicio a través del cual un mensaje es enviado a un grupo y dicho mensaje es entregado a todos sus miembros (comunicación punto a multipunto). En esta acción, el emisor desconoce las identidades de los receptores. Los grupos son la abstracción clave para este tipo de comunicación y están formados por una colección de procesos u objetos que persiguen un objetivo común y cooperan activamente para alcanzarlo. Cada grupo está asociado a un nombre lógico. Los mensajes se destinan a dicho nombre y es un servicio de comunicación en grupo el que se encarga de entregarlo a sus integrantes.

La comunicación en grupo representa una abstracción sobre la comunicación multicast y puede ser implementada sobre multicast IP o mecanismos equivalentes, añadiendo funcionalidades como administración de membresía, detección de fallas y provisión de garantías de ordenamiento y confiabilidad. Con la inclusión de estas características, la comunicación grupal es para multicast IP lo que TCP es para el servicio IP punto a punto. Es así que el paradigma de comunicación grupal es un elemento importante para los sistemas distribuidos, permitiendo la provisión de aplicaciones confiables y de alta disponibilidad. Áreas clave de aplicación incluyen:

Diseminación confiable de información a un número potencialmente grande de clientes.

Soporte para aplicaciones colaborativas.

Soporte para un conjunto de estrategias para tolerancia a fallos, incluida la actualización

consistente de información replicada o la implementación de servidores replicados

altamente disponibles.

Soporte para sistemas de monitoreo y administración, incluyendo, por ejemplo,

estrategias de balanceo de carga.

Grupos de Procesos y Grupos de Objetos

La mayor parte del trabajo en servicios de grupo se enfoca en el concepto de grupos de procesos, lo que quiere decir que las entidades que se comunican son procesos. Los grupos de procesos son una manera viable de solucionar problemas de confiabilidad en sistemas distribuidos. La idea principal es la creación redundante de componentes críticos para que puedan ser reemplazados al presentarse una falla (replicación). De manera general, dichos servicios son relativamente de bajo nivel tomando en cuenta que:

Mensajes son entregados a procesos y no se provee soporte adicional de despacho.

Mensajes son típicamente arrays no estructurados de bytes sin soporte para marshalling

de tipos de datos complejos.

El nivel de servicio provisto por grupos de procesos es similar al de los sockets. En contraste, grupos de objetos proveen un mecanismo de computación grupal de más alto nivel. Un grupo de objetos es una colección de objetos (normalmente instancias de una misma clase) que procesan un mismo conjunto de invocaciones de manera concurrente, cada uno retornando una respuesta. Los objetos cliente no están al tanto de la replicación, invocando operaciones

Page 3: j Groups

3

en un único objeto local que actúa como un proxy para el grupo. El proxy utiliza un sistema de comunicación en grupo para enviar las llamadas a los miembros del objeto grupo. Parámetros de objeto y resultados pasan por un proceso de marshalling (como en RMI).

Pese al potencial de los grupos de objetos, los grupos de procesos todavía son dominantes en términos de uso. Por ejemplo, JGroups presenta un mecanismo de grupos de procesos (aunque no se apega estrictamente a la definición al presentar ciertas particularidades).

Mecanismos Clave

Los mecanismos clave de la arquitectura subyacente de los distintos sistemas de comunicación grupal son un servicio de membresía a grupos integrado a un servicio de multicast confiable.

El objetivo del servicio de membresía es mantener a los miembros consistentemente

informados acerca de cambios en la membresía actual (composición actual) del grupo

mediante la instalación de vistas. El servicio de membresía debe mantener una lista actual

de los integrantes activos y conectados. El resultado de este servicio es lo que se denomina

vista. La composición del grupo puede variar dinámicamente en base a solicitudes

voluntarias de ingresar o abandonar el grupo, o a eventos accidentales como el

colgamiento de un integrante. Las vistas instaladas consisten de una colección de

miembros y representa la percepción de la constitución del grupo que es compartida por

sus componentes. En otras palabras, debe existir un acuerdo entre los miembros sobre la

composición de la vista antes de que esta sea instalada. Tareas principales:

o Proveer una interfaz para cambios en la membresía del grupo: el servicio provee

operaciones para crear y destruir grupos, así como añadir o retirar a procesos de

un grupo. En la mayoría de sistemas, un único proceso puede pertenecer a varios

grupos al mismo tiempo.

o Detección de fallas: el servicio monitorea a los miembros del grupo tanto para

detectar fallas en el proceso en sí, como para detectar elementos inalcanzables

por errores de comunicación (partición por error de red). El detector marca a los

procesos como sospechosos o no sospechosos.

o Notificación a miembros de cambios en la composición.

o Ejecutar expansión de direcciones del grupo: cuando un proceso realiza un

multicast de un mensaje provee el identificador del grupo, no la lista de procesos

en él. El servicio de administración de membresía expande al identificador en la

composición actual del

conjunto para realizar la

entrega. El servicio puede

decidir consistentemente

donde entregar un mensaje

dado, aun cuando la

membresía pueda estar

cambiando durante la

entrega.

Adquirir estas propiedades requiere de lo que se conoce como comunicación en grupo

Page 4: j Groups

4

con vista síncrona. Debe haber una sincronización de la información de vistas y una integración con la entrega de mensajes: dos procesos que instalen el mismo par de vistas en el mismo orden, entregan el mismo conjunto de mensajes entre las instalaciones de estas vistas.

En el ejemplo del gráfico, los servidores S1, S2 y S3 se unen al grupo formando la vista v1. Inmediatamente después, S1 y S2 son particionados de S3. El servicio de administración de membresía reacciona instalando dos vistas v2 y v3. Luego, el particionamiento desaparece y los nodos otra vez pueden formar una única vista v4. Finalmente, el servidor S3 sufre un crash causando la instalación de la vista v5, únicamente con los miembros sobrevivientes.

La tarea del servicio de multicast confiable es permitir a los miembros del grupo

comunicarse utilizando mensajes multicast.

4. JGroups

En terminología más común, un miembro es un nodo y un grupo es un clúster. Un nodo es un proceso que reside en algún host. Los nodos no están restringidos a ejecutarse en un mismo host.

JGroups es un conjunto de herramientas para comunicación en grupo confiable. Procesos pueden unirse a un grupo, enviar mensajes a todos los miembros o a un único miembro y recibir mensajes de otros integrantes del grupo. El sistema lleva un registro de los miembros de cada grupo y notifica el ingreso de nuevos miembros, así como el abandono u ejecución errónea (crash) de alguno de ellos. Los grupos son identificados por su nombre y no tienen que ser creados explícitamente; cuando un proceso se integra a un grupo inexistente el grupo será creado automáticamente. Procesos pertenecientes a un grupo pueden encontrarse en el mismo host, dentro de la misma LAN o en una WAN. Un miembro puede pertenecer a múltiples grupos.

Page 5: j Groups

5

Arquitectura

*El diagrama de arquitectura mostrado en la parte derecha corresponde el diseño de las primeras versiones del toolkit, mientras el de la izquierda es más actual. El diagrama de las primeras versiones refleja la integración existente con la herramienta Ensemble y con otro toolkit denominado iBus, enfocado en la diseminación confiable de mensajes bajo la filosofía publish-suscribe.

El canal (JChannel) representa la interfaz más primitiva para el desarrollo de aplicaciones,

ofreciendo funcionalidad básica de unión, abandono, envío y recepción.

Un proceso interactúa con un grupo mediante un objeto canal, que opera como

manejador del grupo. Para unirse a un grupo y enviar mensajes, un proceso debe crear un

canal y conectarse a él empleando el nombre de grupo. Todos los canales con el mismo

nombre forman un grupo. Los grupos solo existen conceptualmente.

Cada canal tiene una dirección única. El canal siempre conoce quienes son los otros miembros dentro del mismo grupo, una lista de direcciones de los miembros puede ser accedida desde cualquier canal. Dicha lista es lo que se conoce como vista. Un proceso puede seleccionar una dirección de la lista y enviarle un mensaje unicast (también a sí mismo) o un mensaje multicast a todos los miembros de la vista actual (también incluyéndose a sí mismo). Cada vez que un proceso se une o abandona el grupo, o cuando se detecta un crash en un proceso, una nueva vista es enviada a todos los miembros restantes del grupo. Cuando se sospecha que un proceso miembro está caído, un mensaje de sospecha es recibido por todos los integrantes libres de falla. De esta manera, los canales reciben mensajes regulares, notificaciones de vista y de sospecha. Las propiedades del canal típicamente se definen en un archivo XML, pero existe la opción de realizar configuraciones a través de strings simples, URIs, árboles DOM o incluso programáticamente. Los canales son simples y primitivos, ofreciendo la funcionalidad básica para la comunicación en grupo habiendo sido diseñados en base al modelo sencillo de sockets. De esta forma, una aplicación puede hacer uso de solo un pequeño subconjunto de JGroups.

Page 6: j Groups

6

De igual manera, la interfaz de cierta forma minimalista es fácil de entender, el cliente necesita saber alrededor de cinco métodos para poder crear y usar un canal. Proveen recepción y envío asíncrono de mensajes, de cierta forma similar a UDP. Esencialmente, el método send() retorna inmediatamente cuando el mensaje es colocado en la red. Solicitudes conceptuales, o respuestas a solicitudes previas, son recibidas en orden indefinido, y la aplicación debe encargarse de coincidir las respuestas con las solicitudes.

Bloques de construcción (building blocks)

Proveen APIs más sofisticados sobre un canal. Los bloques de construcción crean y usan canales internamente, o requieren la especificación de un canal ya existente al crearse un bloque de construcción. Las aplicaciones se comunican directamente con los bloques de construcción, no con el canal. Su propósito es ofrecer un mayor de nivel de abstracción para la comunicación grupal, evitándoles al desarrollador la escritura de código tedioso y recurrente. También pueden ser descritos como patrones de comunicación que proveen estructuras y algoritmos comúnmente encontrados en comunicación grupal, en forma de clases Java. La interfaz del canal es lo suficientemente simple y pequeña para ser trasladada sobre distintos stacks de protocolos de forma que estos patrones, al solo depender de una implementación de la interfaz (abstracta) del canal, pueden ser usados en la mayoría de instancias de comunicación grupal. Ejemplo de building block:

o MessageDispatcher Los canales son patrones simples para enviar y recibir mensajes asíncronamente. Sin embargo, un número significativo de patrones de comunicación requieren comunicación síncrona. Por ejemplo, un emisor podría querer enviar un mensaje a un grupo y esperar por todas las respuestas. MessageDispatcher provee funcionalidad para lograr este objetivo realizando bloqueo hasta que un número específico de respuestas haya sido receptado.

Stack de protocolos, que implementa las propiedades especificadas para un canal dado.

Page 7: j Groups

7

El stack de protocolos contiene un número de capas en una lista bidireccional. Todos los mensajes enviados o recibidos a través del canal deben pasar por todos los protocolos. Cada capa puede modificar, reordenar, pasar o descartar el mensaje, o añadirle un encabezado. Un mensaje consiste en un campo remitente y destinatario, los cuales son objetos que denotan las direcciones tanto de origen como de destino. Si la dirección de destino es nula, el mensaje es enviado a todos los miembros del grupo. Los campos adicionales son el payload (byte buffer), el cual es usado para llevar información en el mensaje, puede contener, por ejemplo, un objeto serializado; y un header list que es usado por las capas del protocolo para añadir información perteneciente a su funcionalidad en el mensaje. Los header permiten adjuntar información a un mensaje sin alterarlo. Un canal tiene una referencia hacia un objeto de stack de protocolos, el cual es usado para enviar y recibir mensajes. Los datos son enviados a través del stack en forma de eventos, un evento tiene un flag de tipo y un argumento. Cuando un mensaje es enviado al stack por el canal, este es envuelto en un evento, etiquetado como “mensaje” y enviado como argumento. La capa del fondo desenvuelve el mensaje y lo pone en la red, cuando se recibe se envuelve nuevamente y se pasa al stack. Hay que tener claro que los mensajes se intercambian entre diferentes stacks, mientras que los eventos viajan a través de las capas de un protocolo. La composición del stack de protocolos es determinada por el creador del canal. Un archivo XML define los protocolos a usarse y los parámetros correspondientes. La característica principal de JGroups es justamente el stack de protocolos y la flexibilidad de la configuración resultante. Las aplicaciones pueden elegir las características que les gustaría en un clúster simplemente editando el archivo XML mencionado. Por ejemplo, una aplicación puede añadir compresión, simplemente añadiendo el protocolo COMPRESS a la configuración. O puede eliminar la fragmentación debido a que sus mensajes serán siempre más pequeños que 65K (sobre UDP), o debido a que utiliza TCP para el transporte. Otra aplicación podría añadir encriptación y autenticación, por lo que los mensajes están cifrados y sólo los nodos que presenten un certificado X.509 válido pueden unirse al clúster. Las aplicaciones son libres de escribir sus propios protocolos (o ampliar uno ya existente), y añadirlos a la configuración. Puede ser útil, por ejemplo, para añadir un protocolo que realiza un seguimiento de todos los mensajes enviados y recibidos a través de un clúster, para auditoría o con fines estadísticos. Los protocolos usados por JGroups se pueden dividir en las siguientes categorías:

Transporte: envío y recepción de mensajes. UDP utiliza IP multicasting y/o datagramas UDP. TCP utiliza conexiones TCP.

Descubrimiento (Discovery): descubrimiento inicial de nodos.

Fusión (Merging): después que una partición de red se recupera, esto une los sub-clusters de nuevo en uno.

Detección de fallos: seguimiento de los nodos del clúster y notificaciones de accidentes potenciales o errores.

Entrega fiable: se asegura de que un mensaje no se pierde, se reciba sólo una vez, y en el orden en el que un remitente lo envió. Esto se hace a través de la asignación de números de secuencia a cada mensaje y a través de la retransmisión en caso de un mensaje perdido.

Estabilidad: los nodos tienen que guardar en su buffer todos los mensajes (para su posible retransmisión). El protocolo de estabilidad se asegura de que periódicamente (o basado en el tamaño acumulado) los mensajes que se han recibido por todos los nodos del clúster se purguen para que puedan ser recopilados y desechados.

Page 8: j Groups

8

Membresía de grupo: seguimiento de los nodos de un clúster, y notifica a la aplicación cuando un nodo se une y o deja el clúster (incluidos los accidentes).

Control de flujo: se asegura de que el remitente no puede enviar mensajes más rápido que los receptores pueden procesarlos, durante un tiempo. Esto es necesario para evitar situaciones out-of-memory. El control de flujo es una parte fundamental de la estabilidad.

Fragmentación: fragmentar mensajes de gran tamaño en otros más pequeños y la reconstrucción en los receptores.

Transferencia de estado: se asegura de que el estado compartido de un grupo (por ejemplo, todas las sesiones HTTP) es transferido correctamente a un nuevo nodo.

Compresión: comprime los mensajes y los descomprime en los receptores.

Encriptación: encripta mensajes.

Autenticación: evita que un nodo no autorizado se una a un grupo.

5. Ejemplo de Aplicación

Sistema de distribución de tareas en un clúster

En este sistema las tareas se pueden colocar en el clúster y son ejecutados por nodos de trabajo. Los nodos trabajadores (workers) pueden ser añadidos para agregar más potencia de procesamiento, o ser retirados cuando no se tiene mucha carga. Además, las tareas asignadas a los trabajadores que posteriormente dejan de funcionar o tienen errores son reasignadas automáticamente a nodos activos.

En este sistema descentralizado, cada nodo del clúster puede ser a la vez un maestro (que envía tareas) y un esclavo (que ejecuta las tareas y devuelve los resultados).

La idea es muy simple: se tiene un conjunto de nodos, y cada nodo puede enviar a ejecutar tareas en otro nodo del clúster. Así que cada nodo es un peer, en el sentido de que puede tanto enviar y manejar las tareas. En una aplicación de la vida real, los clientes podrían conectarse a cualquiera de los nodos, por ejemplo, a través de TCP o RMI, y presentar tareas a ese nodo, que luego la distribuiría a algún otro nodo (o la manejaría por sí mismo).

Al enviar una tarea, se elige un número entero aleatorio que se asigna al rango de un nodo del clúster. El rango (rank) es la posición de un nodo en la vista, y como la vista es la misma en todos los nodos, el rango identifica al nodo de forma única.

La tarea es entonces enviada por multicast (EXECUTE) hacia el clúster. Cada nodo añade una tarea a un hash map que contiene las tareas y las respectivas direcciones (JGroups) del nodo que las envió.

Cada nodo compara el rango enviado con la tarea con su propio rango. Si no coincide, no se hace nada. Si coincide, el nodo necesita procesar la tarea. Lo hace y devuelve el resultado al remitente.

Cuando el remitente recibe la respuesta (RESULT), envía un mensaje (multicast) REMOVE en el clúster. Cuando REMOVE (T) es recibido, cada nodo elimina T dentro de su hash map.

Si un nodo X se bloquea (crashes), o solo sale, es posible saber qué tareas fueron encomendadas a este nodo buscando dentro de su hash map, los que tengan la clave X. Todas las tareas que aún están presentes en el hash map aún no han sido procesadas y necesitan ser re-ejecutadas, esta vez por un nodo diferente. Esto se realiza mediante la comparación del rango (rank) que incluye la tarea con el rank del nodo, ejecutándola si estos coinciden.

Page 9: j Groups

9

Si un master M sufre un crash después de haber enviado una serie de tareas, pero que todavía no ha recibido los resultados, los esclavos eliminan todas las tareas enviadas por M, ya que M ya no necesita los resultados.

El grupo consta de los nodos A, B, C y D. Los clientes pueden acceder a cualquiera de ellos. Una tarea presentada, por ejemplo, a B por un cliente que podría asignar a la tarea el numero 23. B a continuación envía un mensaje (multicast) de EXECUTE (23, TASK) para todos los nodos del clúster, y cada nodo añade la tarea número 23 a su caché.

Sin embargo, el único nodo procesando la tarea 23 es A (donde resulta estar mapeada la tarea 23), que luego envía el resultado como un RESULT (23, OBJ) hacia B. B devuelve el OBJ resultado al cliente y realiza un multicast de REMOVE (23) a todo el clúster, lo que hace que todos los nodos eliminen la tarea 23 de sus caches. Si A tiene un problema o se cae durante el procesamiento de la tarea 23, algún otro nodo se habría hecho cargo, procesado el resultado y enviándolo de vuelta a B.

6. Conclusiones

Se puede concluir que un sistema implementado con JGroups cumple con los requerimientos de diseño de un sistema distribuido:

o Es tolerante a fallos, tal como se presentó en el ejemplo de aplicación, ya que no existe un servidor central, sino varios nodos que cumplen las mismas funciones. Cada nodo puede actuar como maestro y esclavo, y las tareas son acogidas por un nodo basado en un ID asignado por el remitente (master). Los accidentes (crashes) o el abandono voluntario de nodos no conduce a tareas perdidas ya que el sistema se re-balancea solo y asigna las tareas “huérfanas” a otro nodo en el clúster.

o Es escalable debido a que se pueden agregar más nodos para aumentar el poder de procesamiento o a su vez eliminar nodos si no existe mucha carga. La formación de clústeres es un claro mecanismo de escalabilidad horizontal.

o Es un sistema abierto pues usa estándares reconocidos y además se puede modificar su estructura de acuerdo a las necesidades del propio sistema. El hecho de que su componente central, el canal (Channel y su implementación default JChannel), presente una interfaz sencilla y bien definida permite extender/modificar la funcionalidad de los elementos circundantes de forma independiente de la implementación específica del canal (en la mayoría de casos).

Page 10: j Groups

10

o Heterogeneidad debido a que los nodos pueden estar en distintos hosts, con distintas características. Y permite la ejecución multiplataforma al ser una tecnología Java.

Adicionalmente existe la presencia de transparencia, debido a que el emisor de solicitudes desconoce la identidad de los integrantes de un grupo, así como su localización y la manera en que el grupo afronta la presencia de errores en el conjunto.

7. Bibliografía

Coulouris, George. Dollimore, Jean. Kindberg, Tim. Blair, Gordon. (2011). Distributed Systems: Concepts and Design (Fifth Edition). Estados Unidos: Pearson Education, Inc.

Ban, Bela. Blagojevic, Vladimir. Reliable Group Comunication with JGroups 3.x. Recuperado el 10 de Noviembre de 2013 de http://www.jgroups.org/manual/pdf/master.pdf.

Ban, Bela. Design and implementation of a Design and Implementation of a Reliable Group Communication Toolkit for Java. Recuperado el 10 de Noviembre de 2013 de http://www.cs.cornell.edu/info/projects/JavaGroupsNew/papers/Coots.ps.gz.

Ban, Bela. Implementing Group Protocols Using Dynamic Remote Method Calls. Recuperado el 10 de Noviembre de 2013 de http://www.cs.cornell.edu/info/projects/JavaGroupsNew/papers/rmc.ps.gz.

Montresor, Alberto. (2000). System Support for Programming Object-Oriented Dependable Applications in Partitionable Systems. Recuperado el 10 de Noviembre de 2013 de http://www.informatica.unibo.it/it/ricerca/technical-report/2000/pdfs/2000-10.ps.gz.

Montresor, Alberto. Meline, Hein. (2002). Jgroup Tutorial and Programmer’s Manual. Recuperado el 10 de Noviembre de 2013 de http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.124.7522&rep=rep1&type=pdf

Ban, Bela. (2008). A simple clustered task distribution system. Recuperado el 10 de Noviembre de 2013 de http://www.jgroups.org/taskdistribution/TaskDistribution.html.