Cluster ActiveMQ embebido en Java

De ChuWiki

En ActiveMQ embebido en Java vimos como levantar sobre la marcha un broker ActiveMQ dentro de nuestro programa Java. Veamos aquí primero cómo levantarlo de forma explícita de forma que otros programas puedan conectarse a nuestro broker y después veremos cómo arrancar dos programas java, cada uno con su propio broker, pero configurados de forma que trabajen en cluster. Es decir, que los mensajes que metamos en uno cualquiera de los broker, se puedan retirar en el otro.


Crear un Broker ActiveMQ[editar]

En ActiveMQ embebido en Java, aparte de las librerías de ActiveMQ que necesitamos para todo esto, vimos que se levantaba un broker automáticamente simplemente intentando conectarse a él usando el protocolo "vm" en la cadena de conexión

ActiveMQConnectionFactory connectionFactory = new ActiveMQConnectionFactory("vm://localhost?broker.persistent=false");
 
Connection connection = connectionFactory.createConnection();
connection.start();

Para que el broker ofrezca conexiones al exterior de nuestro programa y otros programas puedan comunicarse enviando o recibiendo mensajes a o desde nuestro broker, tenemos que levantarlo y configurarlo de forma explícita. El código sería parecido al siguiente

BrokerService brokerService = new BrokerService();
brokerService.setBrokerName("consumer");
brokerService.addConnector("tcp://0.0.0.0:61616");
brokerService.setPersistent(false);
brokerService.start();

Veamos los pasos

  • Instanciamos la clase BrokerService de ActiveMQ
  • Le damos un nombre, el que queramos. Este nombre es el que debemos usar más adelante si queremos usar el protocolo "vm" para poder enviarnos mensajes a nosotros mismos de una parte de nuestra aplicación a otra. En el tutorial anterior en que se levantaba el Broker automáticamente, el nombre que se daba era "localhost" puesto que era lo que usábamos en la cadena de conexión "vm://localhost?broker.persistent=false". Como en este ejemplo hemos puesto de nombre "consumer", la cadena de conexión debería ser "vm://consumer?broker.persistent=false"
  • Creamos un conector por medio de addConnector(). Un conector en ActiveMQ es un puerto que abrimos para que otros programas puedan conectarse a nuestro ActiveMQ y enviar mensajes por él. La cadena para el connector en este caso es "tcp://0.0.0.0:61616".
    • tcp es que abrimos una conexión tcp
    • 0.0.0.0 es que queremos que se puedan conectar a nosotros por cualquiera de nuestras IP. Otras opciones serían localhost o 127.0.0.1 si sólo queremos que se puedan conectar a nosotros programas que corran en nuestro mismo ordenador. O si tenemos dos tarjetas de red y nuestro PC tiene dos IPs (por ejemplo, de una LAN interna y de una LAN externa), podemos poner una de ellas (por ejemplo, la de la LAN interna), de forma que sólo podrán conectarse a nosotros programas que corran en la red correspondiente a esa tarjeta (en nuestro ejemplo, sólo admitiríamos conexiones de la LAN interna).
    • 61616 es el puerto que abrimos para escuchar.
  • Indicamos que no queremos persistencia de los mensajes, es decir, no queremos que los mensajes que se envían/reciben se guarden en ningún tipo de base de datos/fichero. Si queremos persistencia, debemos añadir alguna librería adicional de ActiveMQ con el tipo de persistencia (fichero, base de datos,...) que queremos. Si los mensajes se guardan en base de datos/fichero, estarán disponibles si matamos nuestro programa y lo volvemos a levantar. Si no hay persistencia, si matamos nuestro programa, los mensajes que se hayan enviado y no se hayan podido entregar a su destinatario se perderán.
  • Arrancamos el Broker una vez configurado.

Listo, con esto tenemos nuestro Broker levantado y listo para su uso. Cualquier programa externo podría enviar o suscribirse a mensajes usando la cadena de conexión "tcp://<nuestra ip>:61616". Nuestro mismo programa puede usar esa cadena de conexión, o bien la propia de la máquina virtual "vm:consumer", ya que consumer es el nombre que hemos dado.

No ponemos aquí un ejemplo de envío y recepción de mensaje puesto que ya lo tienes en ActiveMQ embebido en Java


Dos Broker en Cluster[editar]

Imaginemos ahora dos programas en Java y que cada uno levanta su propio Broker de ActiveMQ. Queremos que estos dos Broker se conecten entre sí y trabajen en cluster, es decir, que si enviamos un mensaje por uno cualquiera de ellos, podeamos recibirlo en el otro, siendo ActiveMQ el que se encargue de pasar el mensaje de un Broker a otro si hace falta.

El mecanismo es muy sencillo. Cada programa Java debe levantar su propio Broker como hemos visto, pero necesita una pequeña configuración más. Uno de nuestros programas, el que corre en el HOST1, haría el siguiente trozo de código

BrokerService brokerService = new BrokerService();
brokerService.setBrokerName("producer");
brokerService.addConnector(MessageFormat.format("tcp://{0}:{1}", HOST1, PORT_HOST1));
brokerService.addNetworkConnector(MessageFormat.format("static://tcp://{0}:{1}",HOST2, PORT_HOST2));
brokerService.setPersistent(false);
brokerService.start();

El código es muy similar al anterior. Comentamos las diferencias

  • Esta vez le hemos puesto de nombre "producer". El otro Broker levantando por el otro programa Java que correrá en otro PC (HOST2) se llamará "consumer".
  • En el connector ponemos la IP del HOST1 (nuestro PC) o bien cosas como "0.0.0.0" si queremos que nos vean desde cualquier sitio. Si ponemos "localhost" o "127.0.0.1", el otro programa java y el otro Broker tendrán que correr en nuestro mismo PC.
  • Añadimos una conexión de red con addNetworkConnector(). Esta es la línea necesaria para configurar este Broker en cluster con el otro. La cadena de conexión es la siguiente
    • static para indicar que vamos a dar la IP concreta del otro broker. En vez de static pueden ponerse cosas como multicast, de forma que nuestro Broker buscará de forma automática otros Broker que estén en la misma red.
    • La IP del HOST2
    • El puerto que el HOST2 haya abierto para aceptar conexiones de clientes.

Por parte del segundo programa Java que corre en el HOST2, el código es muy similar

BrokerService brokerService = new BrokerService();
brokerService.setBrokerName("consumer");
brokerService.addConnector(MessageFormat.format("tcp://{0}:{1}",HOST2,PORT_HOST2));
brokerService.addNetworkConnector(MessageFormat.format("static://tcp://{0}:{1}",HOST1, PORT_HOST1));
brokerService.setPersistent(false);
brokerService.start();
  • Esta vez lo hemos llamado "consumer"
  • Se añade un conector para que se conecten los clientes. Es a este conector al que debe también conectarse el Broker del HOST1 en su conexión de red.
  • Se añade una conexión de red hacia el Broker de HOST1, usando su IP y el puerto que haya puesto el HOST1 para clientes (su conector).

Y con esto está todo listo. Podemos desde HOST1 meter mensajes en el Broker de HOST1 y el programa en HOST2 puede retirarlos de su propio Broker.


Ejemplo completo[editar]

Tienes el código completo de los dos programas java, en HOST1 y HOST2, en los siguientes enlaces

Están preparados y sólo funcionan si los haces correr en el mismo PC, ya que se buscan en localhost.