JBoss A-MQ : Consumidor de mensagens utilizando protocolo fabric

Introdução

O Fuse Fabric discovery agent utiliza o protocolo fabric para a descoberta de brokers que estão em um grupo específico. Para que isto aconteça o discovery agent precisa que todos os brokers sejam implantados em somente uma fábrica. Quando um cliente tenta se conectar a um broker, o agent procura por todos os brokers disponíveis no registro do fabric e os retorna.

fabric_consumer

Características

  • O protocolo fabric garante failover automaticamente
  • Clientes não precisam saber onde os brokers estão localizados 
  • Funciona como o transporte failover
  • Oferece opções para reconexão:

discovery:(fabric:usa-group)?reconnectDelay=1000&useExponentialBackOff=false

  • Clientes precisam ter a URL do Zookeeper

Como configurar o broker

Para saber em detalhes como fazer o deploy de brokers utilizando o Fuse Fabric, dê uma olhada no post Cluster JBoss A-MQ : Master/Slave Network of Brokers utilizando Fuse Fabric.

 Como configurar o cliente

Para saber em detalhes como criar um client que envia mensagens para o Fuse Fabric, dê uma olhada no post JBoss A-MQ : Produtor de mensagens utilizando protocolo fabric.

Setando o zookeeper.url

Para que o cliente consiga encontrar corretamente o grupo de brokers, precisamos adicionar a propriedade zookeeper.url que indica a instância do Fuse Fabric’s Zookeeper, no meu caso rodando localmente adicionei no pom.xml do meu projeto:

<zookeeper.url>localhost:2181</zookeeper.url>
<zookeeper.password>admin</zookeeper.password>

Download do projeto completo

Consumer-teste.zip

Até o próximo post!


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


Compilando mod_jk no Fedora 18

Pré-requisitos

Instale o compilador gcc

[root@sfantin]# yum install gcc

Instale o módulo gcc-c++

[root@sfantin]# yum install gcc-c++

Instale o Apache

[root@sfantin]# yum install httpd

Compilando o mod_jk

Download do código fonte

tomcat-connectors-1.2.37-src.tar.gz

Descompactar

[root@sfantin tmp]# tar xzvf tomcat-connectors-1.2.37-src.tar.gz

Entrar no diretório

[root@sfantin tmp]# cd tomcat-connectors-1.2.37-src/native

Localize o apxs

[root@sfantin tomcat-connectors-1.2.37-src]# whereis apxs

apxs: /bin/apxs /usr/bin/apxs /usr/share/man/man1/apxs.1.gz

Execute

[root@sfantin native]# ./configure --with-apxs=/usr/bin/apxs

checking build system type… x86_64-unknown-linux-gnu
checking host system type… x86_64-unknown-linux-gnu
checking target system type… x86_64-unknown-linux-gnu
checking for a BSD-compatible install… /bin/install -c
checking whether build environment is sane… yes
checking for gawk… gawk

APRINCLUDEDIR is -I/usr/include/apr-1 -I/usr/include/apr-1
building connector for “apache-2.0”
checking for gcc… gcc -std=gnu99
checking for C compiler default output file name… a.out
checking whether the C compiler works… yes

checking for sys/stat.h… yes

checking for g++… g++
checking whether we are using the GNU C++ compiler… yes
checking whether g++ accepts -g… yes
checking dependency style of g++… none
checking how to run the C++ preprocessor… g++ -E

checking the maximum length of command line arguments… 32768
checking command to parse /bin/nm -B output from gcc -std=gnu99 object… ok
checking for objdir… .libs
checking for ar… ar
checking for ranlib… ranlib
checking for strip… strip
checking if gcc -std=gnu99 supports -c -o file.o… yes
checking whether the gcc -std=gnu99 linker (/bin/ld -m elf_x86_64) supports shared libraries… yes

checking for shl_load in -ldld… no
checking for dlopen… no
checking for dlopen in -ldl… yes
checking whether a program can dlopen itself… yes
checking whether a statically linked program can dlopen itself… yes

checking for dlopen in -ldl… (cached) yes
checking whether a program can dlopen itself… (cached) yes
checking whether a statically linked program can dlopen itself… (cached) yes
appending configuration tag “F77” to libtool
checking if libtool supports shared libraries… yes
checking whether to build shared libraries… yes
checking whether to build static libraries… yes
checking for f95 option to produce PIC… -fPIC
checking if f95 PIC flag -fPIC works… yes
checking if f95 supports -c -o file.o… yes
checking whether the f95 linker (/bin/ld -m elf_x86_64) supports shared libraries… yes
checking dynamic linker characteristics… GNU/Linux ld.so
checking how to hardcode library paths into programs… immediate
checking whether stripping libraries is possible… yes

configure: creating ./config.status
config.status: creating Makefile
config.status: creating apache-1.3/Makefile

config.status: creating common/config.h
config.status: executing depfiles commands

Execute o comando

[root@sfantin native]# make

Making all in common
make[1]: Entering directory `/tmp/tomcat-connectors-1.2.37-src/native/common’
/usr/lib64/apr-1/build/libtool –silent –mode=compile gcc -std=gnu99 -I/usr/include/httpd -DHAVE_CONFIG_H -O2 -g -pipe -Wall -Wp,-

Making all in apache-2.0
make[1]: Entering directory `/tmp/tomcat-connectors-1.2.37-src/native/apache-2.0′
/usr/lib64/apr-1/build/libtool –silent –mode=compile gcc -std=gnu99 -I/usr/include/httpd -DHAVE_CONFIG_H -DUSE_APACHE_MD5 -I ../common -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector –param=ssp-buffer-size=4 -m64 -mtune=generic -pthread -DHAVE_APR -I/usr/include/apr-1 -I/usr/include/apr-1 -DHAVE_CONFIG_H -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -c mod_jk.c -o mod_jk.lo
/usr/lib64/apr-1/build/libtool –silent –mode=link gcc -std=gnu99 -I/usr/include/httpd -DHAVE_CONFIG_H -DUSE_APACHE_MD5 -I ../common -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -O2 -g -pipe -Wall -Wp,-D_FORTIFY_SOURCE=2 -fexceptions -fstack-protector –param=ssp-buffer-size=4 -m64 -mtune=generic -pthread -DHAVE_APR -I/usr/include/apr-1 -I/usr/include/apr-1 -DHAVE_CONFIG_H -pthread -DLINUX=2 -D_REENTRANT -D_GNU_SOURCE -Wl,-z,relro,-z,now -o mod_jk.la -module -rpath /usr/lib64/httpd/modules -avoid-version mod_jk.lo ../common/jk_ajp12_worker.lo ../common/jk_connect.lo ../common/jk_msg_buff.lo ../common/jk_util.lo ../common/jk_ajp13.lo ../common/jk_pool.lo ../common/jk_worker.lo ../common/jk_ajp13_worker.lo ../common/jk_lb_worker.lo ../common/jk_sockbuf.lo ../common/jk_map.lo ../common/jk_uri_worker_map.lo ../common/jk_ajp14.lo ../common/jk_ajp14_worker.lo ../common/jk_md5.lo ../common/jk_shm.lo ../common/jk_ajp_common.lo ../common/jk_context.lo ../common/jk_url.lo ../common/jk_status.lo
../scripts/build/instdso.sh SH_LIBTOOL=’/usr/lib64/apr-1/build/libtool –silent’ mod_jk.la `pwd`
/usr/lib64/apr-1/build/libtool –silent –mode=install cp mod_jk.la /tmp/tomcat-connectors-1.2.37-src/native/apache-2.0/
libtool: install: warning: remember to run `libtool –finish /usr/lib64/httpd/modules’
make[1]: Leaving directory `/tmp/tomcat-connectors-1.2.37-src/native/apache-2.0′
make[1]: Entering directory `/tmp/tomcat-connectors-1.2.37-src/native’
make[1]: Nothing to be done for `all-am’.
make[1]: Leaving directory `/tmp/tomcat-connectors-1.2.37-src/native’
target=”all”; \
list=’common apache-2.0′; \
for i in $list; do \
echo “Making $target in $i”; \
if test “$i” != “.”; then \
(cd $i && make $target) || exit 1; \
fi; \
done;
Making all in common
make[1]: Entering directory `/tmp/tomcat-connectors-1.2.37-src/native/common’
make[1]: Nothing to be done for `all’.
make[1]: Leaving directory `/tmp/tomcat-connectors-1.2.37-src/native/common’
Making all in apache-2.0
make[1]: Entering directory `/tmp/tomcat-connectors-1.2.37-src/native/apache-2.0′
../scripts/build/instdso.sh SH_LIBTOOL=’/usr/lib64/apr-1/build/libtool –silent’ mod_jk.la `pwd`
/usr/lib64/apr-1/build/libtool –silent –mode=install cp mod_jk.la /tmp/tomcat-connectors-1.2.37-src/native/apache-2.0/
libtool: install: warning: remember to run `libtool –finish /usr/lib64/httpd/modules’
make[1]: Leaving directory `/tmp/tomcat-connectors-1.2.37-src/native/apache-2.0′

Execute o comando

[root@sfantin native]# make install

Making install in common
make[1]: Entering directory `/tmp/tomcat-connectors-1.2.37-src/native/common’
make[1]: Nothing to be done for `install’.
make[1]: Leaving directory `/tmp/tomcat-connectors-1.2.37-src/native/common’
Making install in apache-2.0
make[1]: Entering directory `/tmp/tomcat-connectors-1.2.37-src/native/apache-2.0′

Installing files to Apache Modules Directory…
/usr/bin/apxs -i mod_jk.la
/usr/lib64/httpd/build/instdso.sh SH_LIBTOOL=’/usr/lib64/apr-1/build/libtool’ mod_jk.la /usr/lib64/httpd/modules
/usr/lib64/apr-1/build/libtool –mode=install install mod_jk.la /usr/lib64/httpd/modules/
libtool: install: install .libs/mod_jk.so /usr/lib64/httpd/modules/mod_jk.so
libtool: install: install .libs/mod_jk.lai /usr/lib64/httpd/modules/mod_jk.la
libtool: install: install .libs/mod_jk.a /usr/lib64/httpd/modules/mod_jk.a
libtool: install: chmod 644 /usr/lib64/httpd/modules/mod_jk.a
libtool: install: ranlib /usr/lib64/httpd/modules/mod_jk.a
libtool: finish: PATH=”/usr/local/apache-maven/apache-maven-3.0.5/bin:/usr/lib64/qt-3.3/bin:/usr/lib64/ccache:/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin:/root/bin:/sbin” ldconfig -n /usr/lib64/httpd/modules
———————————————————————-
Libraries have been installed in:
/usr/lib64/httpd/modules

If you ever happen to want to link against installed libraries
in a given directory, LIBDIR, you must either use libtool, and
specify the full pathname of the library, or use the `-LLIBDIR’
flag during linking and do at least one of the following:
– add LIBDIR to the `LD_LIBRARY_PATH’ environment variable
during execution
– add LIBDIR to the `LD_RUN_PATH’ environment variable
during linking
– use the `-Wl,-rpath -Wl,LIBDIR’ linker flag
– have your system administrator add LIBDIR to `/etc/ld.so.conf’

See any operating system documentation about shared libraries for
more information, such as the ld(1) and ld.so(8) manual pages.
———————————————————————-
chmod 755 /usr/lib64/httpd/modules/mod_jk.so

Please be sure to arrange /etc/httpd/conf/httpd.conf…

make[1]: Leaving directory `/tmp/tomcat-connectors-1.2.37-src/native/apache-2.0′
make[1]: Entering directory `/tmp/tomcat-connectors-1.2.37-src/native’
make[2]: Entering directory `/tmp/tomcat-connectors-1.2.37-src/native’
make[2]: Nothing to be done for `install-exec-am’.
make[2]: Nothing to be done for `install-data-am’.
make[2]: Leaving directory `/tmp/tomcat-connectors-1.2.37-src/native’
make[1]: Leaving directory `/tmp/tomcat-connectors-1.2.37-src/native’

O conector que acabou de ser criado está em:

/usr/lib64/httpd/modules/mod_jk.so

PS: dica do meu caro Raul Leite

Pronto!

 


Configurando mod_cluster no EAP 6 – RHEL/CentOS/Fedora

modcluster_logo_450pxJBoss EAP 6 provê mecanismos de cluster com a ajuda de algumas extensões: JGroups, Infinispan e modcluster.

  • JGroups: responsável pela comunicação entre as instâncias
  • Infinispan: responsável por cache e replicação de sessão
  • modcluster: permite a utilização do httpd como load balancer

Características

  • Alta Disponibilidade (HA): execução sem interrupção
  • Escalabilidade: capacidade de manipular um grande número de requisições
  • Failover: até quando instâncias falharem, as requisições dos clientes serão atendidas
  • Tolerância à falha: o serviço é garantido até mesmo se failover ocorrer

Post anterior

Este post é continuação do post Configurando Domain Mode no EAP 6 – RHEL/CentOS/Fedora.

O link anterior é um pré-requisito e ensina a configurar algumas instâncias do EAP 6 em modo Domain. Depois de ter feito toda a configuração descrita no post, continue a partir daqui.

Ambiente clusterizado

As funcionalidades do mod_cluster estarão diponíveis entre as instâncias de um determinado grupo de servidores, no nosso caso utilizaremos o main-server-group. Assim, todas as instâncias deste grupo farão parte do ambiente clusterizado.

Arquitetura

arq_modcluster

High Availability

Podemos utlizar tanto o perfil ha quanto o full-ha, pois ambos provêm as funcionalidades específicas de cluster fornecidas por modcluster e jGroups.

Escolhi o perfil full-ha (poderia ter escolhido ha sem problema algum) para demonstrar como uma modificação na configuração é feita de maneira simples.

No arquivo domain.xml altere o perfil do grupo para full-ha e o socket-binding para full-ha-sockets. Se quiser copiar/colar o trecho depois, ele já está alterado corretamente:

Antes

<server-groups>
<server-group name=”main-server-group” profile=”full”>
<jvm name=”default”>
<heap size=”1303m” max-size=”1303m”/>
<permgen max-size=”256m”/>
</jvm>
<socket-binding-group ref=”full-sockets”/>
</server-group>
<server-group name=”other-server-group” profile=”full-ha”>
<jvm name=”default”>
<heap size=”1303m” max-size=”1303m”/>
<permgen max-size=”256m”/>
</jvm>
<socket-binding-group ref=”full-ha-sockets”/>
</server-group>
</server-groups>

Depois

<server-groups>
<server-group name=”main-server-group” profile=”full-ha“>
<jvm name=”default”>
<heap size=”1303m” max-size=”1303m”/>
<permgen max-size=”256m”/>
</jvm>
<socket-binding-group ref=”full-ha-sockets“/>
</server-group>
<server-group name=”other-server-group” profile=”full-ha“>
<jvm name=”default”>
<heap size=”1303m” max-size=”1303m”/>
<permgen max-size=”256m”/>
</jvm>
<socket-binding-group ref=”full-ha-sockets“/>
</server-group>
</server-groups>

Agora temos que definir uma senha para o HornetQ no perfil full-ha (que é o perfil do nosso main-server-group).

Procure pela linha:

<cluster-password>${jboss.messaging.cluster.password:CHANGE ME!!}</cluster-password>

Obs: preste atenção neste momento, pois existem vários perfis (default, full e ha) neste mesmo arquivo. No nosso caso iremos alterar o <profile name=”full-ha”> que fica aproximadamente na linha 1099 e a altere para:

<cluster-password>123456</cluster-password>

Esta modificação é necessária porque o sistema de mensageria HornetQ utiliza um sistema de cluster separado do jGroups. Assim que habilitamos o cluster, precisamos definir uma senha.

jboss.node.name

Existe um recurso muito interessante, principalmente quando o utilizamos em cluster, pois podemos saber exatamente “quem é quem” no sistema.

Adicione o atributo instance-id=”${jboss.node.name}” subsystem web:

<profile name=”full-ha”>

Aprox. linha 1254:

Antes

<subsystem xmlns=”urn:jboss:domain:web:1.1″ default-virtual-server=”default-host” native=”false”>

Depois

<subsystem xmlns=”urn:jboss:domain:web:1.1″ default-virtual-server=”default-host” instance-id=”${jboss.node.name}” native=”false”>

Instalando o mod_cluster

Baixe o mod_cluster versão 1.2.0: http://www.jboss.org/mod_cluster/downloads/1-2-0-Final

Baixe o pacote correspondente ao seu sistema operacional. No meu caso eu baixei o mod_cluster-1.2.0.Final-linux2-x64-ssl, pois a arquitetura do meu RHEL 6 é x86_64.

Os arquivos que iremos utilizar estão no diretório mod_cluster-1.2.0.Final-linux2-x64-ssl/opt/jboss/httpd/lib/httpd/modules, porém utilizaremos somente os seguinte módulos:

  • mod_proxy_cluster.so
  • mod_advertise.so
  • mod_slotmem.so
  • mod_manager.so

Extraia os arquivos acima para o diretório /etc/httpd/modules. No meu caso instalei na minha máquina física RHEL 6.4 que tem o IP 192.168.122.0.

Depois de copiar os arquivos para o diretório modules, edite o arquivo /etc/httpd/conf/httpd.conf.

O primeiro passo é comentar o módulo abaixo adicionando no início da linha o caracter #:

# LoadModule proxy_balancer_module modules/mod_proxy_balancer.so

O segundo passo é comentar a linha Listen 127.0.0.1:80 adicionando #. Vamos comentá-la, pois adicionaremos outra customizada a seguir:

# Listen 127.0.0.1:80

Obs: Pode ser que ao invés de Listen 127.0.0.1:80 esteja Listen localhost:80

No fim do arquivo httpd.conf, cole o seguinte trecho:

LoadModule slotmem_module modules/mod_slotmem.so
LoadModule manager_module modules/mod_manager.so
LoadModule proxy_cluster_module modules/mod_proxy_cluster.so
LoadModule advertise_module modules/mod_advertise.so

Listen 192.168.122.0:10001
<VirtualHost 192.168.122.0:10001>

<Location /mod_cluster-manager>
SetHandler mod_cluster-manager
Order deny,allow
Deny from all
Allow from 192.168.122.
</Location>

KeepAliveTimeout 60
MaxKeepAliveRequests 0

ManagerBalancerName mycluster
ServerAdvertise On
EnableMCPMReceive

</VirtualHost>

Testando o Cluster

Primeiramente, vamos acessar todas as instâncias diretamente:

http://host1:8080/cluster-demo

http://host1:8230/cluster-demo

http://host1:8330/cluster-demo

Obs: o server-three está definido com auto-start=false, portanto está fora do ar.

http://host2:8440/cluster-demo

http://host2:8580/cluster-demo

Agora vamos acessar o Apache Web Server (httpd) que irá receber todas as requisições e as encaminhará para as instâncias que estão no grupo main-server-group:

http://host1/cluster-demo

Se a URL acima responder normalmente, o mod_cluster está funcionando perfeitamente. Para testar basta acessar de vários navegadores diferentes e visualizar nos terminais quais instâncias que estão recebendo as requisições. O interessante é acessar através do link acima e verificar qual instância recebeu a requisição e em seguida derrubá-la. Se o mod_cluster foi configurado corretamente, mesmo com algumas instâncias fora do ar, o sistema estará disponível para o usuário.

mod_cluster-manager

Para acessar o mod_cluster-manager acesse a URL:

http://192.168.122.0:10001/mod_cluster-manager

Espero ter ajudado!


Configurando Domain Mode no EAP 6 – RHEL/CentOS/Fedora

Domain Mode é uma das principais features do Enterprise Application Platform (EAP), pois permite o gerenciamento de toda a configuração das instâncias de um único ponto, no caso o arquivo domain.xml através do Domain Controller. Toda as instâncias gerenciadas pelo Domain Controller são chamadas de Host Controllers e podem ter suas configurações alteradas dependendo da necessidade. Podemos utilizar grupos de instâncias, assim podemos definir grupos instâncias que estão em diferentes hosts. 

domain

Obs: Vale lembrar que a utilizando Domain Mode não quer dizer que o ambiente está em Cluster, mas que todos os Host Controllers do ambiente estão compartilhando a configuração do Domain Controller.

Quando utilizamos Domain Mode três processos separados são iniciados:

  • Process Controller: responsável por gerenciar e start/restartar os processos;
  • Host Controller: um dos Host Controllers é o Domain Controller e os outros são slaves;
  • Server Instance: instância do servidor de aplicação;

Instalação

Instalação do JDK: https://serjaum.wordpress.com/2013/04/21/instalando-oracle-jdk6/

Instalação do EAP6: https://serjaum.wordpress.com/2013/04/21/instalando-eap-6/

Hosts

Neste exemplo utilizei duas máquinas virtuais com os respectivos IPs:

Nome da máquina: host1
IP: 192.168.122.1

Nome da máquina: host2
IP: 192.168.122.2

Obs: utilizei o KVM como hypervisor, que por padrão configura a comunicação entre todos as máquinas virtuais.

Dica: Se estiver utilizando o VirtualBox, segue >>> aqui <<< um tutorial que ensina como configurar a comunicação entre as máquinas envolvidas.

Precisamos fazer com que as máquinas host1 e host2 consigam se conectar entre si através do hostname.

Adicione no arquivo /etc/hosts os nomes das duas máquinas com seus respectivos IPs:

# vim /etc/hosts

192.168.122.1 host1
192.168.122.2 host2

Obs: faça a mesma alteração no host2

Desabilitando o Firewall

O próximo passo é desabilitar o firewall. Como root, execute o seguinte comando em ambas as máquinas:

# service iptables stop 

O comando acima desabilita o firewall.

# chkconfig iptables off 

O comando acima garante que o firewall não será ativado nos próximos boots.

Desabilitando o SELinux

Como root, altere nas duas máquinas o parâmetro SELINUX=enforcing para SELINUX=disabled

# vim /etc/sysconfig/selinux

Para confirmar que as duas máquinas estão se conectando entre si, tente executar o comando ping passando como parâmetro o IP da outra máquina.

No terminal da host1, digite:

$ ping host2

Execute o mesmo na host2.

Por questões didáticas, vamos alterar as instâncias da máquina host2, no arquivo host.xml:

Antes: 

<servers>
 <server name="server-one" group="main-server-group">
 <!-- Remote JPDA debugging for a specific server
 <jvm name="default">
 <jvm-options>
 <option value="-Xrunjdwp:transport=dt_socket,address=8787,server=y,suspend=n"/>
 </jvm-options>
 </jvm>
 -->
 </server>
 <server name="server-two" group="main-server-group" auto-start="true">
 <!-- server-two avoids port conflicts by incrementing the ports in
 the default socket-group declared in the server-group -->
 <socket-bindings port-offset="150"/>
 </server>
 <server name="server-three" group="other-server-group" auto-start="false">
 <!-- server-three avoids port conflicts by incrementing the ports in
 the default socket-group declared in the server-group -->
 <socket-bindings port-offset="250"/>
 </server>
 </servers>

Depois: 

<servers>
<server name="server-four" group="main-server-group" auto-start="true">
<socket-bindings port-offset="400"/>
</server>
<server name="server-five" group="main-server-group" auto-start="true">
<socket-bindings port-offset="500"/>
</server>
</servers>

Percebam que adicionei um port-offset nas instâncias para não termos conflitos de portas. Então, para acessarmos o instância server-four temos que apontar o browser para a URL:

http://host2:8440

Para acessarmos o server-five:

http://host2:8580

Domain Controller (host1)

Na máquina host1 aponte o terminal para o diretório /opt/jboss-eap-6.0/bin e execute o seguinte comando:

$ ./add-user.sh

[user1@host1 bin]$ ./add-user.sh

What type of user do you wish to add?
a) Management User (mgmt-users.properties)
b) Application User (application-users.properties)
(a): a

Enter the details of the new user to add.
Realm (ManagementRealm) :
Username : master
Password : 123456
Re-enter Password :
About to add user ‘master’ for realm ‘ManagementRealm’
Is this correct yes/no? yes
Added user ‘master’ to file ‘/opt/jboss-eap-6.0/standalone/configuration/mgmt-users.properties’
Added user ‘master’ to file ‘/opt/jboss-eap-6.0/domain/configuration/mgmt-users.properties’
Is this new user going to be used for one AS process to connect to another AS process?
e.g. for a slave host controller connecting to the master or for a Remoting connection for server to server EJB calls.
yes/no? yes
To represent the user add the following to the server-identities definition <secret value=”MTIzNDU2″ />

Iniciar o Domain Controller

Na máquina host1 aponte o terminal para o diretório /opt/jboss-eap-6.0/bin e execute o seguinte comando:

./domain.sh -b host1 -bmanagement host1

Com o EAP no ar, aponte o browser para a seguinte URL:

http://host1:9990

Username : master
Password : 123456

Na máquina host1 aponte o terminal para o diretório /opt/jboss-eap-6.0/bin e execute o seguinte comando:

[user1@host1 bin]$ ./add-user.sh

What type of user do you wish to add?
a) Management User (mgmt-users.properties)
b) Application User (application-users.properties)
(a): a

Enter the details of the new user to add.
Realm (ManagementRealm) :
Username : slave
Password : 123456
Re-enter Password :
About to add user ‘slave’ for realm ‘ManagementRealm’
Is this correct yes/no? yes
Added user ‘slave’ to file ‘/opt/jboss-eap-6.0/standalone/configuration/mgmt-users.properties’
Added user ‘slave’ to file ‘/opt/jboss-eap-6.0/domain/configuration/mgmt-users.properties’
Is this new user going to be used for one AS process to connect to another AS process?
e.g. for a slave host controller connecting to the master or for a Remoting connection for server to server EJB calls.
yes/no? yes
To represent the user add the following to the server-identities definition <secret value=”MTIzNDU2″ />

Obs: o usuário “slave” será utilizado para se conectar ao master através do host2, portanto devemos definir o nome “slave” para o host2. Tal tarefa será descrita adiante.

Host Controller (host2)

Remova o arquivo /opt/jboss-eap-6.0/domain/configuration/domain.xml, pois a configuração do host1 será utilizada pelo host2. Esta é a ideia quando se monta um grupo de servidores: ter um grupo de servidores compartilhando uma única configuração, nessa caso o arquivo domain.xml do host1.

$ rm domain.xml

Altere o arquivo /opt/jboss-eap-6.0/domain/configuration/host.xml

Linha 3 aprox.)

<host name=”slave” xmlns=”urn:jboss:domain:1.3″>

Linha 36 aprox.)

<domain-controller>
<remote host=”host1″ port=”9999″ security-realm=”ManagementRealm”/>
</domain-controller>

Lembram do usuário “slave” criado na primeira máquina através do add-user.sh? Precisamos converter a senha 123456 para Base64. Há diversas maneiras para codificar uma senha, vamos utilizar o link http://www.base64online.com tal tarefa. O resultado é o seguinte:

MTIzNDU2

Obs: em versões mais novas do EAP 6, como esta que estamos utilizando, esta tarefa não é necessária, pois a senha já é convertida automaticamente assim que criamos algum usuário:

To represent the user add the following to the server-identities definition <secret value=”MTIzNDU2” />

Depois de codificar a senha para Base64, precisamos adicioná-la dentro da tag <server-identities> do arquivo host.xml do host2:

Linha 8 aprox.)

<security-realm name=”ManagementRealm”>
<server-identities>
<secret value=”MTIzNDU2” />
</server-identities>

Iniciar o Host Controller

./domain.sh -b host2 -bmanagement host2

No próximo post ensinarei como montar um cluster utilizando algumas instâncias do EAP6.


VirtualBox – Rede Interna entre Máquinas Virtuais

Uma alternativa bem útil quando se deseja montar uma rede virtual é a função de Host-Only Network fornecida pelo VirtualBox, que pode ser utilizada para criar uma rede que contém o host e um conjunto de máquinas virtuais, sem a necessidade de interface de rede física do host. Em vez disso, uma interface de rede virtual (semelhante a uma interface de loopback) é criada na máquina, fornecendo conectividade entre máquinas virtuais e o host.

Criando a rede virtual

Para criar uma rede interna clique no menu –> Preferences –> Network.

Clique no desenho da plaquinha de rede com sinal de mais para criar uma nova Host-Only Network:

vboxnet0

Uma nova rede com o nome de vboxnet0 foi criada.

Podemos utilizar a rede com os IPs default, porém fiz as seguintes alterações:

adapter

dhcp_server

OK. Quando alguma máquina virtual foi iniciada, um IP será atribuído à mesma.

No meu ambiente iniciei a máquina virtual CentOS e depois Fedora:

CentOS 

centos

O IP 192.168.56.101 foi atribuído à máquina virtual CentOS.

Fedora

fedora

O IP 192.168.56.102 foi atribuído à máquina virtual Fedora.

ping 192.168.56.102

ping

Pronto! Temos uma rede composta de máquinas virtuais!