Cluster JBoss A-MQ : Failover em Network of Brokers – Store and Forward

Introdução

ActiveMQ suporta o conceito de Network of Brokers, onde os brokers estão remotos e as aplicações precisam de comunicar com eles de uma forma confiável. 
Na abordagem store and forward no contexto de Network of Brokers as mensagens são passadas de um broker para outro até chegar em um consumidor, onde esta mensagem estará em posse de somente um broker ao mesmo tempo, ou seja, nesta abordagen podemos garantir failover por causa do protocolo de mesmo nome, porém não podemos garantir Alta Disponibilidade (HA).
Seguindo este paradigma, ter uma arquitetura centralizada de brokers onde todos os clientes se conectam não parece uma boa ideia. Vamos supor que um broker esteja guardando uma certa quantidade de mensagens em seu persistent store e por alguma motivo ele falha. Estas mensagens estarão em posse deste broker até que ele retorne.

network_brokers_static

Solução

Utilização de Master/Slave.

Bidirecional

Por padrão esta abordagem opera somente de forma unidirecional a logicamente envia mensagens para a rede, porém uma simples configuração permite que a rede seja bidirecional onde o broker pode tanto enviar quanto receber mensagens.

Casos de Uso

  • Geralmente em grandes redes onde os produtores das mensagens estão em uma LAN e os consumidores estão em outra LAN. Neste caso pode-se usar um broker em cada LAN como se fosse um broker que irá concentrar a comunicação tentando minimizar o número de conexões entre WAN que liga as duas LANs.
  • Store and forward pode ser encontrado em ambientes de firewalls ou SSL entre redes.
  • Quando o Sistema Operacional (SO) não suporta um número grande de sockets, pode-se usar store and forward para conectar um número grande de clientes utilizando uma rede lógica.

Duas configurações

Red Hat JBoss A-MQ suporta dois diferentes tipos de configurações para formar uma Network of Brokers:

  • Static (proposta deste tutorial): onde é necessário saber o IP de todos os brokers que fazem parte da rede e inscrevê-los previamente no arquivo de configuração;
  • Multicast: utilização de Discovery para detecção automática dos brokers;

Como acessar o broker?

Clientes ActiveMQ Java e C++ provêem um protocolo de transferência chamado de failover,  que tenta se conectar automaticamente ao novo broker master sem perda de mensagens. Os clientes dos brokers utilizarão o seguinte protocolo de transporte:

failover://(tcp://host1:61616)

Dica: a URI acima irá tentar automaticamente estabelecer uma conexão com o mesmo broker no caso de queda. Portanto, mesmo que haja somente um broker no ambiente, é recomendado que o protocolo failover seja utilizado, pois no caso de queda, ele tentará se conectar novamente.

Instalação

1) Download

O Red Hat JBoss A-MQ 6.0 pode ser baixo aqui: https://www.jboss.org/products/amq.html

Obs: disponível somente para fins de Desenvolvimento.

2) Descompactar

Descompacte o A-MQ nas duas máquinas. No meu caso descopactei em /opt de cada RHEL virtual.

3) Conectividade

Tenha certeza que as máquinas conseguem se comunicar entre elas: localhost (física fazendo papel de cliente através o Fuse IDE), host1 (virtual) e host2 (virtual) e host3 (virtual).

Configurações host1

1) users.properties 

Altere o arquivo $jboss-a-mq-diretorio/etc/users.properties descomentando a linha:

#admin=admin,admin

2) system.properties

Altere o arquivo $jboss-a-mq-diretorio/etc/system.properties substituindo localhost pelo hostname da máquina virtual. No meu caso é o host1:

# Activemq configuration
activemq.port = 61616
activemq.host = host1 
activemq.url = tcp://${activemq.host}:${activemq.port}

3) activemq.xml

Altere o arquivo $jboss-a-mq-diretorio/etc/activemq.xml

<broker xmlns=”http://activemq.apache.org/schema/core&#8221;
brokerName=”amq1
useJmx=”true”
dataDirectory=”${data}”>

<managementContext>
<managementContext connectorPort=”1091” createConnector=”false”/>
</managementContext>

<networkConnectors>
<networkConnector name=“amq1:nc”
uri=”static:(failover:(tcp://host2:61616,tcp://host3:61616))”
dynamicOnly=”true”
networkTTL=”3″
duplex=”true”/>
</networkConnectors>

<persistenceAdapter>
<kahaDB directory=”${data}/kahadb”/>
</persistenceAdapter>

<plugins>
<loggingBrokerPlugin logAll=”false” logConnectionEvents=”true”/>
</plugins>

<systemUsage>
<systemUsage>
<memoryUsage>
<memoryUsage limit=”20 mb”/>
</memoryUsage>
<storeUsage>
<storeUsage limit=”1 gb” name=”foo”/>
</storeUsage>
<tempUsage>
<tempUsage limit=”100 mb”/>
</tempUsage>
</systemUsage>
</systemUsage>

<transportConnectors>
<transportConnector name=”openwire” uri=”tcp://host1:61616″/>
</transportConnectors>

</broker>

Configurações host2

1) users.properties

Altere o arquivo $jboss-a-mq-diretorio/etc/users.properties descomentando a linha:

#admin=admin,admin

2) system.properties

Altere o arquivo $jboss-a-mq-diretorio/etc/system.properties substituindo localhost pelo hostname da máquina virtual. No meu caso é o host2:

# Activemq configuration
activemq.port = 61616
activemq.host = host2 
activemq.url = tcp://${activemq.host}:${activemq.port}

3) activemq.xml

<broker xmlns=”http://activemq.apache.org/schema/core&#8221;
brokerName=”amq2
useJmx=”true”
dataDirectory=”${data}”>

<managementContext>
<managementContext connectorPort=”1092” createConnector=”false”/>
</managementContext>

<persistenceAdapter>
<kahaDB directory=”${data}/kahadb”/>
</persistenceAdapter>

<plugins>
<loggingBrokerPlugin logAll=”false” logConnectionEvents=”true”/>
</plugins>

<systemUsage>
<systemUsage>
<memoryUsage>
<memoryUsage limit=”20 mb”/>
</memoryUsage>
<storeUsage>
<storeUsage limit=”1 gb” name=”foo”/>
</storeUsage>
<tempUsage>
<tempUsage limit=”100 mb”/>
</tempUsage>
</systemUsage>
</systemUsage>

<transportConnectors>
<transportConnector name=”openwire” uri=”tcp://host2:61616″/>
</transportConnectors>
</broker>

Configurações host3

1) users.properties

Altere o arquivo $jboss-a-mq-diretorio/etc/users.properties descomentando a linha:

#admin=admin,admin

2) system.properties

Altere o arquivo $jboss-a-mq-diretorio/etc/system.properties substituindo localhost pelo hostname da máquina virtual. No meu caso é o host3:

# Activemq configuration
activemq.port = 61616
activemq.host = host3 
activemq.url = tcp://${activemq.host}:${activemq.port}

3) activemq.xml

<broker xmlns=”http://activemq.apache.org/schema/core&#8221;
brokerName=”amq3
useJmx=”true”
dataDirectory=”${data}”>

<managementContext>
<managementContext connectorPort=”1093” createConnector=”false”/>
</managementContext>

<persistenceAdapter>
<kahaDB directory=”${data}/kahadb”/>
</persistenceAdapter>

<plugins>
<loggingBrokerPlugin logAll=”false” logConnectionEvents=”true”/>
</plugins>

<systemUsage>
<systemUsage>
<memoryUsage>
<memoryUsage limit=”20 mb”/>
</memoryUsage>
<storeUsage>
<storeUsage limit=”1 gb” name=”foo”/>
</storeUsage>
<tempUsage>
<tempUsage limit=”100 mb”/>
</tempUsage>
</systemUsage>
</systemUsage>

<transportConnectors>
<transportConnector name=”openwire” uri=”tcp://host3:61616″/>
</transportConnectors>
</broker>

Start do host1

Execute o seguinte arquivo $jboss-a-mq-diretorio/bin 

./amq 

Start do host2

Execute o seguinte arquivo $jboss-a-mq-diretorio/bin 

./amq 

Start do host3

Execute o seguinte arquivo $jboss-a-mq-diretorio/bin 

./amq 

Na maquina física

import javax.jms.Connection;
import javax.jms.DeliveryMode;
import javax.jms.MessageProducer;
import javax.jms.Queue;
import javax.jms.Session;

import org.apache.activemq.ActiveMQConnectionFactory;

public class SampleClient {

public static void main(String[] args) throws Exception {
ActiveMQConnectionFactory factory =

new ActiveMQConnectionFactory(“failover:(tcp://host1:61616)?timeout=1000“);

Connection connection = factory.createConnection(“admin”, “admin”);
Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
connection.start();
Queue queue = session.createQueue(“SampleQueue“);
MessageProducer producer = session.createProducer(queue);

producer.setDeliveryMode(DeliveryMode.NON_PERSISTENT);

// send messages
for (int i = 0; i < 100; i++) {
producer.send(session.createTextMessage(i + ” message”));
System.out.println(“Sent message ” + i);
Thread.sleep(1000);
}
producer.close(); session.close(); connection.close();
}
}

O programa acima envia 100 mensagens para o broker.

static_networkbrokers

Consumindo as mensagens

Disponibilizei logo abaixo as classes que produzem e consomem as mensagens dos brokers, além de toda configuração dos brokers.

Download de todos os recursos

  • activemq1.xml
  • activemq1.xml
  • activemq1.xml
  • Producer
  • Consumer

>>> Mensageria.zip 

Até o próximo post!



Deixe uma resposta

Preencha os seus dados abaixo ou clique em um ícone para log in:

Logotipo do WordPress.com

Você está comentando utilizando sua conta WordPress.com. Sair / Alterar )

Imagem do Twitter

Você está comentando utilizando sua conta Twitter. Sair / Alterar )

Foto do Facebook

Você está comentando utilizando sua conta Facebook. Sair / Alterar )

Foto do Google+

Você está comentando utilizando sua conta Google+. Sair / Alterar )

Conectando a %s