Cluster JBoss A-MQ : Master/Slave com File System compartilhado

Introdução

O ponto fundamental desta abordagem é prover Alta Disponibilidade (HA) em cenários de produção utilizando ActiveMQ. Na configuração master/slave existe somente um broker Master e vários slaves aguardando a falha do master para serem promovidos, na verdade somente um será. A falha do master é detectada pela falta de conectividade entre o master e os slaves.
masterslave

Duas configurações

A versão 6.0 do Red Hat JBoss A-MQ suporta dois diferentes tipos de configurações master/slave:

  • Shared nothing, onde cada broker ActiveMQ tem seu próprio message storage;
  • Shared storage (proposta deste tutorial), onde múltiplos brokers ActiveMQ brokers podem se contectar ao message store (banco relacional ou sistema de arquivos) compartilhado mas somente um broker estará ativo ao mesmo tempo. Nenhum intervenção manual é requerida para manter a integridade de aplicação. Nenhum limitação de número de brokers slave. O master terá o lock do DB.

Três tipos de Message Stores

  1. File System Master Slave compartilhado: por exemplo SAN, NFS, etc.
  2. JDBC Master Slave:  Um banco de dados compartilhado. Não é a melhor opção tem termos de performance porque não utiliza journal de alta performance, mas a configuração é bem simples.

Por que usar File System ao invés de Banco de Dados?

Utilizar file system compartilhado é a melhor solução para prover Alta Disponibilidade, pois combina o alto throughput do KahaDB e a simplicidade de se utilizar um recurso compartilhado. KahaDB é extremamente rápido e é limitado somente pela performance do file system.
Não é necessário configuração adicional dos brokers e não existe limite de slaves acessando o file system.

Neste tutorial utilizarei o Network File System (NFS) como file system compartilhado, porém poderia ter escolhido outros como Global File System (GFS) 2 ou Storage Area Network (SAN).

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,tcp://host2:61616)?randomize=false

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), host1 (virtual) e host2 (virtual).

4) Diretório compartilhado

Criei um /shared na minha máquina física utilizando NFS e o exportei para as máquinas virtuais: host1 e host2

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=”broker_host1
dataDirectory=”${data}”
useJmx=”true”
start=”false”>

<transportConnectors>
<!– Na perspectiva do cliente a uri é usada para criar uma conexão com o broker para enviar/receber mensages –>
<transportConnector name=”openwire” uri=”tcp://host1:61616″/>
</transportConnectors>

<persistenceAdapter>
<kahaDB directory=“/shared“>
</persistenceAdapter>

<managementContext>
<managementContext createConnector=”trueconnectorPort=”1091″/>
</managementContext>

Obs: coloquei somente os trechos alterados.

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

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

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

<transportConnectors>
<!– Na perspectiva do cliente a uri é usada para criar uma conexão com o broker para enviar/receber mensages –>
<transportConnector name=”openwire” uri=”tcp://host2:61616″/>
</transportConnectors>

<persistenceAdapter>
<kahaDB directory=“/shared“>
</persistenceAdapter>

<managementContext>
<managementContext createConnector=”true” connectorPort=”1092″/>
</managementContext>

Obs: coloquei somente os trechos alterados.

Start do host1

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

./amq 

Console host1

2013-11-05 12:26:30,843 | INFO | veMQ Broker: amq | PListStoreImpl | tore.kahadb.plist.PListStoreImpl 331 | 104 – org.apache.activemq.activemq-osgi – 5.8.0.redhat-60024 | PListStore:[/opt/jboss-a-mq-6.0.0.redhat-024/data/amq/broker_host1/tmp_storage] started
2013-11-05 12:26:31,004 | INFO | JMX connector | ManagementContext | q.broker.jmx.ManagementContext$1 138 | 104 – org.apache.activemq.activemq-osgi – 5.8.0.redhat-60024 | JMX consoles can connect to service:jmx:rmi:///jndi/rmi://localhost:1091/jmxrmi
2013-11-05 12:26:31,016 | INFO | veMQ Broker: amq | BrokerService | he.activemq.broker.BrokerService 595 | 104 – org.apache.activemq.activemq-osgi – 5.8.0.redhat-60024 | Using Persistence Adapter: KahaDBPersistenceAdapter[/shared]
2013-11-05 12:26:32,252 | INFO | veMQ Broker: amq | MessageDatabase | .kahadb.MessageDatabase$Metadata 147 | 104 – org.apache.activemq.activemq-osgi – 5.8.0.redhat-60024 | KahaDB is version 4
2013-11-05 12:26:32,264 | INFO | veMQ Broker: amq | MessageDatabase | emq.store.kahadb.MessageDatabase 552 | 104 – org.apache.activemq.activemq-osgi – 5.8.0.redhat-60024 | Recovering from the journal …
2013-11-05 12:26:32,265 | INFO | veMQ Broker: amq | MessageDatabase | emq.store.kahadb.MessageDatabase 565 | 104 – org.apache.activemq.activemq-osgi – 5.8.0.redhat-60024 | Recovery replayed 1 operations from the journal in 0.009 seconds.
2013-11-05 12:26:32,403 | INFO | veMQ Broker: amq | BrokerService | he.activemq.broker.BrokerService 634 | 104 – org.apache.activemq.activemq-osgi – 5.8.0.redhat-60024 | Apache ActiveMQ 5.8.0.redhat-60024 (broker_host1, ID:host1-60970-1383672392281-0:1) is starting
2013-11-05 12:26:32,434 | INFO | veMQ Broker: amq | TransportServerThreadSupport | ort.TransportServerThreadSupport 72 | 104 – org.apache.activemq.activemq-osgi – 5.8.0.redhat-60024 | Listening for connections at: tcp://host1:61616
2013-11-05 12:26:32,435 | INFO | veMQ Broker: amq | TransportConnector | tivemq.broker.TransportConnector 254 | 104 – org.apache.activemq.activemq-osgi – 5.8.0.redhat-60024 | Connector openwire Started
2013-11-05 12:26:32,437 | INFO | veMQ Broker: amq | BrokerService | he.activemq.broker.BrokerService 658 | 104 – org.apache.activemq.activemq-osgi – 5.8.0.redhat-60024 | Apache ActiveMQ 5.8.0.redhat-60024 (broker_host1, ID:host1-60970-1383672392281-0:1) started
2013-11-05 12:26:32,476 | INFO | veMQ Broker: amq | ActiveMQServiceFactory | q.fabric.ActiveMQServiceFactory$ 52 | 120 – org.jboss.amq.mq-fabric – 6.0.0.redhat-024 | Broker amq has started.
2013-11-05 12:35:59,091 | INFO | qtp252820188-194 | RemoteJMXBrokerFacade | tivemq.web.RemoteJMXBrokerFacade 153 | 133 – org.jboss.amq.mq-web-console – 5.8.0.redhat-60024 | Connected via JMX to the broker at service:jmx:rmi:///jndi/rmi://host1:1091/karaf-root

Start do host2

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

./amq 

Console host2

2013-11-05 12:26:37,533 | INFO | veMQ Broker: amq | PListStoreImpl | tore.kahadb.plist.PListStoreImpl 331 | 104 – org.apache.activemq.activemq-osgi – 5.8.0.redhat-60024 | PListStore:[/opt/jboss-a-mq-6.0.0.redhat-024/data/amq/broker_host2/tmp_storage] started
2013-11-05 12:26:37,588 | INFO | Executor: 1 | DispatcherServlet | ork.web.servlet.FrameworkServlet 463 | 133 – org.jboss.amq.mq-web-console – 5.8.0.redhat-60024 | FrameworkServlet ‘dispatcher’: initialization completed in 338 ms
2013-11-05 12:26:37,657 | INFO | JMX connector | ManagementContext | q.broker.jmx.ManagementContext$1 138 | 104 – org.apache.activemq.activemq-osgi – 5.8.0.redhat-60024 | JMX consoles can connect to service:jmx:rmi:///jndi/rmi://localhost:1092/jmxrmi
2013-11-05 12:26:37,667 | INFO | veMQ Broker: amq | BrokerService | he.activemq.broker.BrokerService 595 | 104 – org.apache.activemq.activemq-osgi – 5.8.0.redhat-60024 | Using Persistence Adapter: KahaDBPersistenceAdapter[/shared]
2013-11-05 12:26:37,778 | INFO | veMQ Broker: amq | SharedFileLocker | .activemq.store.SharedFileLocker 58 | 104 – org.apache.activemq.activemq-osgi – 5.8.0.redhat-60024 | Database /shared/lock is locked… waiting 10 seconds for the database to be unlocked. Reason: java.io.IOException: File ‘/shared/lock’ could not be locked.
2013-11-05 12:26:47,899 | INFO | veMQ Broker: amq | SharedFileLocker | .activemq.store.SharedFileLocker 58 | 104 – org.apache.activemq.activemq-osgi – 5.8.0.redhat-60024 | Database /shared/lock is locked… waiting 10 seconds for the database to be unlocked. Reason: java.io.IOException: File ‘/shared/lock’ could not be locked.
2013-11-05 12:26:58,012 | INFO | veMQ Broker: amq | SharedFileLocker | .activemq.store.SharedFileLocker 58 | 104 – org.apache.activemq.activemq-osgi – 5.8.0.redhat-60024 | Database /shared/lock is locked… waiting 10 seconds for the database to be unlocked. Reason: java.io.IOException: File ‘/shared/lock’ could not be locked.

Ou seja: aguardando a liberação do lock, tentando checar a cada 10 segundos

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,tcp://maquina2: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.

fuse-amq

Vou deixar enviando até completar 10 mensagens e em seguida derrubarei o broker que está recebendo as mensagens:

[ActiveMQ Task-1] FailoverTransport INFO Successfully connected to tcp://host1:61616
Sent message 0
Sent message 1
Sent message 2
Sent message 3
Sent message 4
Sent message 5
Sent message 6
Sent message 7
Sent message 8
Sent message 9
Sent message 10
[na/192.168.122.153:61616@52382] FailoverTransport WARN Transport (tcp://192.168.122.153:61616) failed, reason: java.io.EOFException, attempting to automatically reconnect
[ActiveMQ Task-1] FailoverTransport INFO Successfully reconnected to tcp://host2:61616
Sent message 11
Sent message 12
Sent message 13
Sent message 14
Sent message 15
Sent message 16
Sent message 17
Sent message 18
Sent message 19
Sent message 20

Acessando o console

http://host2:8181/activemqweb/queueGraph.jsp

queue-view



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