Infinispan – Remote Client-Server no protocolo Hot Rod

Vamos criar um ambiente onde a aplicação não está na mesma JVM que o Infinispan. Esta abordagem pode ser utilizada quando temos um cliente desenvolvido em outra linguagem de programação, como por exemplo .NET ou C++, assim estas linguagens podem fazer uso do Infinispan como um servidor remoto.

Ambiente

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

Cliente: Aplicação Java na JVM do host 192.168.122.0

Servidor:  Infinispan na JVM do host 102.168.122.1

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.

Arquitetura

remote-client-server-final

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

Dica: Faça um teste utilizando ping para garantir que as duas máquinas estão se comunicando.

Download do Infinispan

Download: Infinispan 6.0.0.Alpha2 servers (HotRod, REST, Memcached)

Configurando o Servidor 

Depois de baixar o Infinispan, descompacte-o em um diretório de sua preferência. No meu caso utilizei o /opt.

Start do servidor

Para iniciar o Infinispan digite o seguinte comando substituindo o IP corretamente.

[user1@host1 bin]$ ./standalone.sh -b 102.168.122.1

=========================================================================

JBoss Bootstrap Environment

JBOSS_HOME: /opt/infinispan-server-6.0.0.Alpha2

JAVA: /usr/java/jdk1.6.0_39/bin/java

JAVA_OPTS: -server -XX:+UseCompressedOops -Xms64m -Xmx512m -XX:MaxPermSize=256m -Djava.net.preferIPv4Stack=true -Djboss.modules.system.pkgs=org.jboss.byteman -Djava.awt.headless=true

=========================================================================

17:17:41,647 INFO [org.jboss.modules] (main) JBoss Modules version 1.2.0.CR1
17:17:42,490 INFO [org.jboss.msc] (main) JBoss MSC version 1.0.4.GA
17:17:42,962 INFO [org.jboss.as] (MSC service thread 1-1) JBAS015899: JBoss Infinispan Server 6.0.0.Alpha2 (AS 7.2.0.Final) starting
17:17:48,509 INFO [org.xnio] (MSC service thread 1-1) XNIO Version 3.0.7.GA
17:17:48,537 INFO [org.jboss.as.server] (Controller Boot Thread) JBAS015888: Creating http management service using socket-binding (management-http)
17:17:48,561 INFO [org.xnio.nio] (MSC service thread 1-1) XNIO NIO Implementation Version 3.0.7.GA
17:17:48,621 INFO [org.jboss.remoting] (MSC service thread 1-1) JBoss Remoting version 3.2.14.GA
17:17:48,899 INFO [org.jboss.as.clustering.infinispan] (ServerService Thread Pool — 17) JBAS010280: Activating Infinispan subsystem.
17:17:48,935 INFO [org.jboss.as.naming] (ServerService Thread Pool — 21) JBAS011800: Activating Naming Subsystem
17:17:48,980 INFO [org.jboss.as.security] (ServerService Thread Pool — 23) JBAS013171: Activating Security Subsystem
17:17:49,214 INFO [org.jboss.as.jsf] (ServerService Thread Pool — 27) JBAS012605: Activated the following JSF Implementations: [main, 1.2]
17:17:49,239 INFO [org.jboss.as.security] (MSC service thread 1-2) JBAS013170: Current PicketBox version=4.0.15.Final
17:17:50,131 INFO [org.jboss.as.naming] (MSC service thread 1-1) JBAS011802: Starting Naming Service
17:17:50,167 INFO [org.jboss.as.connector.logging] (MSC service thread 1-2) JBAS010408: Starting JCA Subsystem (JBoss IronJacamar 1.0.15.Final)
17:17:51,852 INFO [org.apache.coyote.ajp] (MSC service thread 1-1) JBWEB003046: Starting Coyote AJP/1.3 on ajp-host1/192.168.122.1:8009
17:17:51,854 INFO [org.apache.coyote.http11] (MSC service thread 1-2) JBWEB003001: Coyote HTTP/1.1 initializing on : http-host1/192.168.122.1:8080
17:17:52,222 INFO [org.apache.coyote.http11] (MSC service thread 1-2) JBWEB003000: Coyote HTTP/1.1 starting on: http-host1/192.168.122.1:8080
17:17:55,284 INFO [org.infinispan.server.endpoint] (MSC service thread 1-2) JDGS010000: HotRodServer starting
17:17:55,317 INFO [org.infinispan.server.endpoint] (MSC service thread 1-2) JDGS010001: HotRodServer listening on 192.168.122.1:11222
17:17:55,961 INFO [org.infinispan.server.endpoint] (MSC service thread 1-1) JDGS010000: WebSocketServer starting
17:17:55,970 INFO [org.infinispan.server.endpoint] (MSC service thread 1-1) JDGS010001: WebSocketServer listening on 192.168.122.1:8181
17:17:57,931 INFO [org.infinispan.factories.GlobalComponentRegistry] (MSC service thread 1-2) ISPN000128: Infinispan version: Infinispan ‘Infinium’ 6.0.0.Alpha2
17:17:59,385 INFO [org.infinispan.jmx.CacheJmxRegistration] (MSC service thread 1-2) ISPN000031: MBeans were successfully registered to the platform MBean server.
17:17:59,394 INFO [org.jboss.as.clustering.infinispan] (MSC service thread 1-2) JBAS010281: Started default cache from local container
17:18:00,381 INFO [org.infinispan.jmx.CacheJmxRegistration] (MSC service thread 1-2) ISPN000031: MBeans were successfully registered to the platform MBean server.
17:18:00,388 INFO [org.jboss.as.clustering.infinispan] (MSC service thread 1-2) JBAS010281: Started jboss-web-policy cache from security container
17:18:00,387 INFO [org.infinispan.jmx.CacheJmxRegistration] (MSC service thread 1-1) ISPN000031: MBeans were successfully registered to the platform MBean server.
17:18:00,396 INFO [org.jboss.as.clustering.infinispan] (MSC service thread 1-1) JBAS010281: Started other cache from security container
17:18:00,474 INFO [org.infinispan.jmx.CacheJmxRegistration] (MSC service thread 1-2) ISPN000031: MBeans were successfully registered to the platform MBean server.
17:18:00,479 INFO [org.jboss.as.clustering.infinispan] (MSC service thread 1-2) JBAS010281: Started memcachedCache cache from local container
17:18:00,488 INFO [org.infinispan.server.endpoint] (MSC service thread 1-2) JDGS010000: REST starting
17:18:00,495 INFO [org.infinispan.jmx.CacheJmxRegistration] (MSC service thread 1-1) ISPN000031: MBeans were successfully registered to the platform MBean server.
17:18:00,499 INFO [org.jboss.as.clustering.infinispan] (MSC service thread 1-1) JBAS010281: Started namedCache cache from local container
17:18:00,506 INFO [org.infinispan.server.endpoint] (MSC service thread 1-1) JDGS010000: MemcachedServer starting
17:18:00,511 INFO [org.infinispan.server.endpoint] (MSC service thread 1-1) JDGS010001: MemcachedServer listening on 192.168.122.1:11211
17:18:01,501 INFO [org.jboss.as.remoting] (MSC service thread 1-1) JBAS017100: Listening on 127.0.0.1:9999
17:18:01,513 INFO [org.jboss.as.remoting] (MSC service thread 1-1) JBAS017100: Listening on 192.168.122.1:4447
17:18:02,783 INFO [org.infinispan.server.endpoint] (MSC service thread 1-2) JDGS010002: REST mapped to /rest
17:18:03,018 INFO [org.jboss.as] (Controller Boot Thread) JBAS015961: Http management interface listening on http://127.0.0.1:9990/management
17:18:03,024 INFO [org.jboss.as] (Controller Boot Thread) JBAS015951: Admin console listening on http://127.0.0.1:9990
17:18:03,029 INFO [org.jboss.as] (Controller Boot Thread) JBAS015874: JBoss Infinispan Server 6.0.0.Alpha2 (AS 7.2.0.Final) started in 23314ms – Started 92 of 130 services (38 services are passive or on-demand)

Configurando o Cliente

Crie um novo projeto Java no Eclipse: File –> New –> Java Project:

project

InfinispanHotRodClient.java

package com.infinispan;
import org.infinispan.client.hotrod.RemoteCache;
import org.infinispan.client.hotrod.RemoteCacheManager;

public class InfinispanHotRodClient {

    public static void main(String[] args) { 
        RemoteCacheManager rcm = new RemoteCacheManager("192.168.122.1");
        RemoteCache rc = rcm.getCache();

        String key = "myKey";

        // Storing data
        rc.put(key, "myValue");

        // Retrieving data
        System.out.printf("Value of key %s is %s", key, rc.get(key));
    }
}

Adicionando as bibliotecas do Infinipan no Cliente

Clique com o direito em cima do projeto –> Build Path –> Configure Build Path: 

Na próxima janela clique no botão Add Library –> User Library –> Next –> User Libraries –> New:

Screenshot from 2013-08-06 21:17:53

Clique no botão Add External JARs… 

Screenshot from 2013-08-06 21:23:15

Selecione todos os jars do diretório /opt/infinispan-server-6.0.0.Alpha2/client/hotrod/java: 

  • commons-pool-1.6.jar
  • infinispan-client-hotrod-6.0.0.Alpha2.jar
  • infinispan-commons-6.0.0.Alpha2.jar
  • jboss-logging-3.1.1.GA.jar
  • jboss-marshalling-1.3.15.GA.jar
  • jboss-marshalling-river-1.3.15.GA.jar

Executando o cliente

Execute a classe Java com o seguinte comando:

Ctrl + F11

Saída no console

Aug 6, 2013 9:29:09 PM org.infinispan.client.hotrod.RemoteCacheManager start
INFO: ISPN004021: Infinispan version: 6.0.0.Alpha2
Value of key myKey is myValue


Infinispan – Grid de Dados

infinispan-banner

Aplicações Enterprise estão se deparando com grandes volumes de dados, e a dificuldade ainda aumenta quando falamos em escalabilidade. Grids de dados são geralmente usados para garantir baixa latência, alta disponibilidade, cache elástico de dados, muitas vezes como soluções NoSQL.

Infinispan é uma plataforma de grid de dados open source altamente escalável, que fornece características como eviction e expiration, persistência, JTA e transações compatíveis com XA, monitoramento via JMX, tudo empacotado em um container de dados concorrente customizado para CPUs multi-core.

Benefícios

  • Conjunto grande de dados: sua principal função é ler e distribuir dados grandes volumes de dados entre nós de uma rede, formando um cluster;
  • Heterogêneo: no ponto de vista software e hardware;
  • Escalabilidade: otimizado para escalar em ambientes que produzem grandes volumes de dados;

Escopos

Enquanto o seu antecessor JBoss Cache era focado em implementar uma simplória biblioteca de cache clusterizado, Infinispan fornece uma platforma de grid de dados com ferramenta de gerenciamento e capacidade de escalamento de milhares de nós.

Java Specification Request (JSR-107)

Cache: Local onde escrevemos dados que foram difíceis de serem calculados/resgatados ou caros para serem resgastados da memória. Assim, desenvolvedores costumam guardar seus itens em estrutura simplórias como Hashtables e ArrayLists, que utilizam a memória.

Para ambientes distribuídos, foi criada a interface javax.cache.Cache que pode ser manipulada pelo CacheManager, que representa uma coleção de caches.

Modos de Operação

1) Replicação

Todos os nós do cluster guardam cópias de todos os itens. Isto provê alta disponibilidade e escalabilidade eficiente ao ler dados, os quais estão replicados entre todos os membros do cluster. Por este motivo não escala tão bem em escritas. Entretando este problema pode ser mitigado configurando o uso de UDP multicast, o qual é capaz de enviar via broadcasting um único update para todos membros do cluster.

  • Replicação assíncrona: é mais rápida que a replicação síncrona (que requer ACK de todos os nós do cluster), porém não há garantia que a mudança ocorrida foi propagada por todos os membros do cluster. Vantagem: fila de replicação, a qual empacota as atualizações em um lote e as replica periodicamente baseado num intervalo de tempo ou quando o tamanho da fila exceder um tamanho definido. Portanto oferece um desempenho mais elevado executando em segundo plano.
  • Replicação síncrona: garante que todo os membros do cluster foram atualizados com sucesso, pois requer ACK de todos eles.

2) Distribuição

Um número fixo de cópias são mantidos para garantir redundância e tolerância a falhas, fornecendo um maior grau de escalabilidade. Este modo se beneficia de escalabilidade linear para escritas e performance estável para leituras. Este modo é o padrão para ambiente clusterizado.

É possível melhorar ainda mais a performance de leitura de dados no modo distributed utilizando o mecanismo L1 cache. Utiliza um consistente algoritmo hash para determinar onde no cluster os itens devem estar e quantas cópias de cada pedaço de dado deve ser mantido no cluster.

3) Invalidação

Não compartilha nenhum dado. É utilizado para remover dados obsoletos de caches remotos. Neste modo o cluster irá se comportar como se tivesse diversos caches locais com capacidade de ouvir a rede invalidando os dados a cada modificação remota que ocorrer.

Benefícios:

  • Tráfego de rede é minimizado, pois mensagens de invalidação são bem menores comparadas às mensagens de atualização que ocorrem no modo de replicação.
  • Os outros caches do cluster procuram por dados modificados utilizando uma maneira preguiçosa, somente quando necessário. Invalidação em cluster é recomendada quando Infinispan é usado como cache de segundo nível para Hibernate.

4) Cache Local

Embora Infinispan tenha um potencial maior em um ambiente distribuído, ele é extremamente útil quando utilizado como um cache local. Nesta aborgadem os dados são armazenados somente no nó local.

Comunicação Síncrona e Assíncrona

Há também a possibilidade adicionar/remover itens do cache assíncronamente utilizando a API non-blocking nos seguintes modos: Replicação, Distribuição e Invalidação.

Formas de Deployment

1) Remote Client-Server

Em algumas situações não é possível que as instâncias do Infinispan residam na mesma JVM da sua aplicação, por exemplo, quando existem clientes .NET ou C++ acessando Infinispan como server remoto.

Remote Cliente-Server fornece um servidor gerenciado, clusterizado e distribuído, que poderá ser acessado remotamente através de Hot Rod, memcached ou API Rest. Neste modo a aplicação não está na mesma JVM do Infinispan.

Protocolos (remote cliente-server)

Hot Rod: protocolo TCP binário para comunicação com o cluster Infinispan remoto. Extremamente rápido, permite load balancing, failover e operações de localização de dados.

Permite que o server converse com os clientes. Se a sua aplicação cliente está conversando com um conjunto de servidores, e a topologia muda (por exemplo, um novo nó adicionado/removido), os servidores podem sinalizar a mudança aos clientes.

Memcached: protocolo que permite a conexão a um daemon memchached non-clustered. Ideal para diminuir o tempo de leitura data sources externos. Utilizado por Twitter e Facebook.

Clientes conseguem se comunicar com o server, porém o server não consegue se comunicar com os clientes, sendo tratado como um servidor burro (Single server daemon).

Rest: Este tipo de interface é entregada através de um arquivo WAR que pode ser deployado em um Servlet container. É uma opção para clientes non-Java ou clientes que utilizam HTTP como mecanismo de transporte para utilização do grid de dados.

2)  Library (embedded mode/p2p)

Fornece acesso local ao um nó de um cluster distribuído. A aplicação terá acesso ao grid de dados dentro da máquina virtual onde se encontra o container. JBoss AS 7 ou Tomcat 7 podem ser utilizados. Neste modo de deployment alguns jars são embutidos na aplicação, onde as instâncias do Infinispan são inicializadas programaticamente.

Gerenciamento Infinispan

Gerenciamento dos nós do Infinispan pode ser feito com a ajuda dos seguintes recursos:

  • JConsole
  • RHQ através de um agente instalado na máquina onde se encontra os membros Infinispan

Transporte

Estende JGroups que garante a comunicação entre os membros do cluster e a descoberta de novos/inválidos membros. A descoberta dos membros do cluster pode acontecer via:

  • UDP: quando o número de membros passa de 100 e está se utilizando o Infinispan como replication e invalidation. Esta opção vem configurada por padrão. 
  • TCP: quando o número de membros é menor que 100 e está se utilizando distribuição de dados. Nesta opção de configuração a descoberta dos membros ainda é feita via UDP, porém o transporte acontece via TCP.
  • EC2: como o multicast não é permitido na Amazon EC2, esta opção utiliza TCP como transporte e S3_PING para descoberta.

Obs: Vale lembrar que a escolha de uma das opções depende de muitas variáveis como características de rede, tamanho e tipo de dados.

Eviction e Expiration

Quando utilizamos estruturas para guardar dados em memória, como por exemplo objetos Java do tipo Map, os dados continuarão em memória para sempre a menos que uma remoção manual aconteça. Com Infinispan existem dois mecanismos para controle de uso de memória: eviction e expiration. Algumas configurações como maxEntries, maximum idle time e lifespan podem ser utilizadas para gerenciar a permanência de itens da memória.

Exemplo:

<namedCache name="evictionCache">
 <eviction
 maxEntries="2000"
 strategy="LRU"/>

Com configuração acima, somente 2000 itens serão mantidos em memória, caso sejam adicionados outros será utilizada a estratégica LRU (Last Recently User) que descarta os primeiros itens menos utilizados recentemente.

Obs: A mesma configuração demonstrada via XML pode ser feita programaticamente. É possível a utilização das duas concomitantemente. Neste caso, a API sobrescreve a configuração XML estática.

Transações

Infinispan é um recurso XA totalmente compatível com JTA, que utiliza um gerenciador de transações para operações distribuídas. Se a transação tiver sucesso o commit acontece, senão o rollback garante que os dados do sistema permaneçam inalterados.

Nos seguintes posts ensinarei como utilizar o Infinispan com alguns casos de uso.