Uma das grandes evoluções do JBoss Messaging sobre o JBossMQ (seu predecessor) foi a robustez da solução em cluster.
Introdução (ou como era com o JBossMQ)
Antigamente, o JBossMQ já era clusterizável (ouch.. neologismo..) mas conseguia isso usando o HA Singleton do JBoss. O JBoss quando configurado em cluster pode ser serviços deployados (ouch de novo..) como singletons através do cluster. Funciona assim: você diz ao JBoss que aquele serviço é um HA Singleton e o JBoss vai garantir a você que em seu cluster haverá sempre um, e apenas um, serviço ativo no cluster (enquanto restar nós no cluster, claro). Essa é uma funcionalidade muito interessante pois permite serviços cluster unaware serem clusterizáveis.
O balanceamento de carga pudia ser feito através dos consumidores: implementando um ReceiverImpl consumidores iriam receber as mensagens a la round robin. Melhor que nada.
JBoss Messaging
O JBoss Messaging é a implementação padrão do JBoss 5. Com o JBoss Messaging a infraestrutura de clusterização melhorou Muito. Podemos agora criar um cluster ativo/ativo, que quando um nó falhar o outro se encarregará de enfileirar suas mensagens. E ainda mais, temos balanceamento de carga de fato: cada conexão aberta usará uma fila diferente, round robin way.
Montando o cluster
Configurar o JBoss Messaging em cluster é extremamente fácil:
- Ative a clusterização nos arquivos de configuração do JBoss Messaging e configure um banco de dados compartilhado;
- User um ConnectionFactory e uma Queue/Topic marcados como clusterizados.
Bom, vamos aos bits. As versões usadas seguem:
- JBoss 5.1.0.GA
- JBoss Messaging 1.4.3.GA (a que vem por padrão)
Configurando o JBoss Messaging
Para fazer o failover, o JBoss Messaging precisa usar um banco de dados compartilhado. Copie de $JBOSS_HOME/examples/config o XML apropriado sobrescrevendo o $JBOSS_HOME/server/all/deploy/messaging/hsqldb-persistence-service.xml (lembre de configurar/iniciar o banco de dados!). Vou usar o MySQL:
rm $JBOSS_HOME/server/all/deploy/messaging/hsqldb-persistence-service.xml cp $JBOSS_HOME/examples/config/mysql-persistence-service.xml $JBOSS_HOME/server/all/deploy/messaging
Ative a clusterização:
<attribute name="Clustered">true</attribute> <attribute name="FailoverOnNodeLeave">true</attribute>
Aponte para apontar para o datasource do seu banco:
<attribute name="DataSource">java:/DefaultDS</attribute>
Criando as filas e factories
Vamos usar o ClusteredConnectionFactory, que é uma factory padrão do JBoss que vá vem configurada em cluster, se quiser ver como é feito: $JBOSS_HOME/server/all/deploy/messaging/connection-factories-service.xml.
Só precisamos criar nossas filas clusterizadas. Adicionem um arquivo $JBOSS_HOME/server/all/deploy/clustered-destinations-service.xml com o seguinte conteúdo:
<?xml version="1.0" encoding="UTF-8"?> <server> <mbean code="org.jboss.jms.server.destination.QueueService" name="jboss.messaging.destination:service=Queue,name=clusteredQueue" xmbean-dd="xmdesc/Queue-xmbean.xml"> <depends optional-attribute-name="ServerPeer">jboss.messaging:service=ServerPeer</depends> <depends>jboss.messaging:service=PostOffice</depends> <attribute name="Clustered">true</attribute> </mbean> </server>
Criando os profiles
Se queremos criar um cluster vamos precisar de dois nós! Então copie o profile all e crie dois outros profiles:
cp -r all jms1 cp -r all jms2
Testando
Vamos subir os dois nós usando o serviço de ServiceBinding do JBoss para não haver conflitos de porta ou ip:
./run.sh -c jms1 -Djboss.service.binding.set=ports-01 -Djboss.messaging.ServerPeerID=1 ./run.sh -c jms2 -Djboss.service.binding.set=ports-02 -Djboss.messaging.ServerPeerID=2
Agora vamos usar uns programinhas que fiz para produzir e consumir mensagens, ele é bem simples e intuitivo e é empacotado junto com os fontes. Vamos usá-lo para testar nosso cluster.
Iniciamos um consumer para cada nó do cluster:
java -cp JmsSample.jar:$JBOSS_HOME/client/jbossall-client.jar net.rafaelliu.jms.JmsConsumer 127.0.0.1:1100 ClusteredConnectionFactory queue/clusteredQueue java -cp JmsSample.jar:$JBOSS_HOME/client/jbossall-client.jar net.rafaelliu.jms.JmsConsumer 127.0.0.1:1200 ClusteredConnectionFactory queue/clusteredQueue
E iniciar o nosso producer:
java -cp JmsSample.jar:$JBOSS_HOME/client/jbossall-client.jar net.rafaelliu.jms.JmsProducer 127.0.0.1:1100,127.0.0.1:1200 ClusteredConnectionFactory queue/clusteredQueue 10 1 "Mensagem de teste"
Viram que as mensagens foram balanceadas? Agora podemos tentar o seguinte:
- fechar um dos consumers: as mensagens são enviadas para o outro consumer;
- fechar um dos consumers enquanto estão sendo enviadas mensagens: o outro consumer assume a partir da última mensagem;
- pausar e despausar um consumer: as mensagens vão sendo enfileiradas e quando despausamos, elas são todas consumidas;
- pausar um consumer e depois fechar: as mensagens vão sendo enfileiradas e quando fechamos, elas são repassadas para o outro nó.
Dá pra brincar muito!
Futuro
Atualmente, sendo empacotado junto com o último Milestone do JBoss 6, o serviço de mensageria foi trocado pelo HornetQ. Isso significa ainda outra evolução na área do MOM para a JBoss. Vamos ver se quando for para GA não escrevo sobre ele. Até a próxima o/
PS: para produção dêem uma olhada nos parâmetros DefaultPreserveOrdering e SuckerPassword.
Binário: http://github.com/downloads/rafaelliu/rafaelliu.net/JmsSample.jar












