Os contêineres, os microsserviços e o NoSQL formam um trio incrível para criar seus aplicativos modernos. Esses aplicativos precisam ser ágeis, atender às demandas dos clientes em constante evolução, ser difundidos e funcionar em plataformas móveis, da Web e de IoT.
Este blog explicará uma pilha simples de microsserviços usando Enxame WildFly, Dockere Couchbase. O código completo e as instruções deste blog estão documentados em: github.com/arun-gupta/wildfly-swarm-couchbase.
Primeiro, vamos entender os principais componentes dessa pilha!
Enxame WildFly permite empacotar e executar aplicativos JavaEE, empacotando-os com apenas o suficiente do tempo de execução do servidor para java -jar seu aplicativo. Com a descoberta de serviços incorporada, logon único usando o Keycloak, monitoramento usando o Hawkulare muitos outros recursos, o WildFly Swarm fornece todos os componentes necessários para desenvolver seu microsserviço.
Docker para Mac oferece suporte nativo para a execução de contêineres do Docker no Mac OSX. Ele se baseia em Hypervisor.framework no OSX. O mecanismo do Docker é executado em uma distribuição do Alpine Linux em cima de um xhyve Máquina virtual, e até mesmo a VM é gerenciada pelo Docker. Não há necessidade de usar o Docker Machine ou o VirtualBox, e ele se integra ao modelo de sandbox de segurança do OSX. A DockerCon 2016 removeu a restrição da versão beta privada do Docker para Mac e, portanto, está disponível para todos agora. 
NoSQL oferece a agilidade e a flexibilidade dos bancos de dados sem esquema. Isso permite que o aplicativo evolua de forma independente e rápida sem passar por migrações complicadas de banco de dados. O Couchbase oferece um verdadeiro dimensionamento horizontal com arquitetura homogêneaem oposição à arquitetura mestre/escravo não escalável. Ele também oferece auto-sharding, Linguagem de consulta semelhante a SQL para JSON (N1QL), banco de dados móvel e sincronização com o servidor de back-end, e muito mais. O aplicativo de amostra completo deste blog está em: github.com/arun-gupta/wildfly-swarm-couchbase.
Aplicativo WildFly Swarm
Vamos dar uma olhada no endpoint REST do Java EE:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package com.couchbase.wildfly.swarm; . . . @Path("airline") public class AirlineResource { @Inject Database database; @GET public String getAll() { N1qlQuery query = N1qlQuery.simple("SELECT * FROM `travel-sample` LIMIT 10"); N1qlQueryResult result = database.getBucket().query(query); return result.allRows().toString(); } . . . } |
Ele usa a anotação JAX-RS padrão para converter um POJO em um endpoint REST. API Java do Couchbase fornecem uma API fluente e usam a instrução N1QL para consultar os documentos e retornar os resultados. A instrução N1QL retorna os primeiros 10 elementos do resultado da consulta. Saiba mais sobre a sintaxe N1QL neste tutorial interativo. A abstração do banco de dados é definida como:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
package com.couchbase.wildfly.swarm; . . . @Singleton @Startup public class Database { CouchbaseCluster cluster; Bucket bucket; public CouchbaseCluster getCluster() { if (null == cluster) { String couchbaseURI = System.getenv("COUCHBASE_URI"); if (null == couchbaseURI) { System.err.println("WARING: No COUCHBASE_URI specified, defaulting to localhost"); couchbaseURI = "localhost:8093"; } System.out.println("Couchbase endpoint: " + System.getenv("COUCHBASE_URI")); cluster = CouchbaseCluster.create(couchbaseURI); } return cluster; } public Bucket getBucket() { if (null == bucket) { bucket = getCluster().openBucket("travel-sample"); } return bucket; } } |
Esse é um EJB singleton que é inicializado com antecedência. Ele usa SDK Java do Couchbase para se conectar ao Couchbase. O endpoint do banco de dados pode ser especificado usando o parâmetro COUCHBASE_URI variável de ambiente. O próximo passo é pom.xml para configurar o WildFly Swarm e Cliente Java do Couchbase:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
org.wildfly.swarm bom ${version.wildfly-swarm} pom import javax javaee-web-api 7.0 provided org.wildfly.swarm jaxrs-cdi org.wildfly.swarm ejb com.couchbase.client java-client 2.2.5 |
Ele usa a "lista de materiais" do WildFly Swarm para extrair todas as dependências. Somente as dependências específicas necessárias para a compilação são especificadas em . Em seguida, eles são empacotados no "fat jar". O plug-in Maven do WildFly Swarm é usado para empacotar e executar o aplicativo:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
org.wildfly.swarm wildfly-swarm-plugin ${version.wildfly-swarm} package ${COUCHBASE_URI} |
COUCHBASE_URI é usado para ler o host de onde o servidor de banco de dados do Couchbase está sendo executado.
Executar o Couchbase Server
Execute o servidor Couchbase usando o Docker para Mac:
|
1 |
docker run -d --name db -p 8091-8093:8091-8093 -p 11210:11210 arungupta/couchbase |
O arungupta/couchbase é construído sobre o imagem padrão do Couchbase e usa API REST do Couchbase para configurar o servidor. Aguarde alguns minutos para que o bucket de amostra seja preenchido com os documentos JSON. Invoque o Ferramenta CLI do Couchbase cbq criar um índice primário no bucket de amostra:
|
1 |
docker run -it --link db:db arungupta/couchbase cbq -u Administrator -p password -engine https://db:8093 -s "create primary index `travel-sample-primary-index` on `travel-sample`;" |
Isso mostrará a saída como:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Connected to : https://db:8093/. Type Ctrl-D or QUIT to exit. Path to history file for the shell : /root/.cbq_history { "requestID": "d0b2e4dd-b702-49e2-971c-a4c640ddb498", "signature": null, "results": [ ], "status": "success", "metrics": { "elapsedTime": "3.154540272s", "executionTime": "3.154493281s", "resultCount": 0, "resultSize": 0 } } |
Essa saída mostra que o resultado da criação do índice foi bem-sucedido. Uma das vantagens de executar o Docker para Mac é que todos os contêineres podem ser acessados em localhost. Isso significa que Console da Web do Couchbase pode ser acessado em localhost:8091. 
Essa tela garante que o Couchbase esteja configurado corretamente.
Executar o microsserviço WildFly Swarm
Empacote e execute o microsserviço autônomo como:
|
1 |
mvn wildfly-swarm:run |
Se o Couchbase estiver sendo executado em um host diferente, o comando será alterado para:
|
1 |
mvn -DCOUCHBASE_URI= wildfly-swarm:run |
Ele mostra a saída como:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
[INFO] Scanning for projects... [INFO] [INFO] ------------------------------------------------------------------------ [INFO] Building nosql-microservices 1.0-SNAPSHOT [INFO] ------------------------------------------------------------------------ [INFO] . . . 2016-06-27 22:21:47,170 WARN [org.jboss.as.dependency.private] (MSC service thread 1-6) WFLYSRV0018: Deployment "deployment.nosql-microservices.war" is using a private module ("org.jboss.jts:main") which may be changed or removed in future versions without notice. 2016-06-27 22:21:47,203 INFO [org.jboss.weld.deployer] (MSC service thread 1-1) WFLYWELD0003: Processing weld deployment nosql-microservices.war 2016-06-27 22:21:47,542 INFO [org.hibernate.validator.internal.util.Version] (MSC service thread 1-1) HV000001: Hibernate Validator 5.2.3.Final 2016-06-27 22:21:47,600 INFO [org.jboss.as.ejb3.deployment] (MSC service thread 1-1) WFLYEJB0473: JNDI bindings for session bean named 'Database' in deployment unit 'deployment "nosql-microservices.war"' are as follows: java:global/nosql-microservices/Database!com.couchbase.wildfly.swarm.Database java:app/nosql-microservices/Database!com.couchbase.wildfly.swarm.Database java:module/Database!com.couchbase.wildfly.swarm.Database java:global/nosql-microservices/Database java:app/nosql-microservices/Database java:module/Database 2016-06-27 22:21:47,731 INFO [org.jboss.weld.deployer] (MSC service thread 1-3) WFLYWELD0006: Starting Services for CDI deployment: nosql-microservices.war 2016-06-27 22:21:47,758 INFO [org.jboss.weld.Version] (MSC service thread 1-3) WELD-000900: 2.3.2 (Final) 2016-06-27 22:21:47,780 INFO [org.wildfly.extension.undertow] (MSC service thread 1-1) WFLYUT0018: Host default-host starting 2016-06-27 22:21:47,788 INFO [org.jboss.weld.deployer] (MSC service thread 1-8) WFLYWELD0009: Starting weld service for deployment nosql-microservices.war 2016-06-27 22:21:48,180 INFO [stdout] (ServerService Thread Pool -- 10) Couchbase endpoint: 2016-06-27 22:21:48,275 INFO [com.couchbase.client.core.CouchbaseCore] (ServerService Thread Pool -- 10) CouchbaseEnvironment: {sslEnabled=false, sslKeystoreFile='null', sslKeystorePassword='null', queryEnabled=false, queryPort=8093, bootstrapHttpEnabled=true, bootstrapCarrierEnabled=true, bootstrapHttpDirectPort=8091, bootstrapHttpSslPort=18091, bootstrapCarrierDirectPort=11210, bootstrapCarrierSslPort=11207, ioPoolSize=8, computationPoolSize=8, responseBufferSize=16384, requestBufferSize=16384, kvServiceEndpoints=1, viewServiceEndpoints=1, queryServiceEndpoints=1, searchServiceEndpoints=1, ioPool=NioEventLoopGroup, coreScheduler=CoreScheduler, eventBus=DefaultEventBus, packageNameAndVersion=couchbase-jvm-core/1.2.5 (git: 1.2.5), dcpEnabled=false, retryStrategy=BestEffort, maxRequestLifetime=75000, retryDelay=ExponentialDelay{growBy 1.0 MICROSECONDS, powers of 2; lower=100, upper=100000}, reconnectDelay=ExponentialDelay{growBy 1.0 MILLISECONDS, powers of 2; lower=32, upper=4096}, observeIntervalDelay=ExponentialDelay{growBy 1.0 MICROSECONDS, powers of 2; lower=10, upper=100000}, keepAliveInterval=30000, autoreleaseAfter=2000, bufferPoolingEnabled=true, tcpNodelayEnabled=true, mutationTokensEnabled=false, socketConnectTimeout=1000, dcpConnectionBufferSize=20971520, dcpConnectionBufferAckThreshold=0.2, queryTimeout=75000, viewTimeout=75000, kvTimeout=2500, connectTimeout=5000, disconnectTimeout=25000, dnsSrvEnabled=false} 2016-06-27 22:21:48,829 INFO [com.couchbase.client.core.node.Node] (cb-io-1-1) Connected to Node localhost 2016-06-27 22:21:49,035 INFO [com.couchbase.client.core.config.ConfigurationProvider] (cb-computations-1) Opened bucket travel-sample 2016-06-27 22:21:49,415 INFO [org.jboss.resteasy.resteasy_jaxrs.i18n] (ServerService Thread Pool -- 10) RESTEASY002225: Deploying javax.ws.rs.core.Application: class com.couchbase.wildfly.swarm.MyApplication 2016-06-27 22:21:49,438 INFO [org.wildfly.extension.undertow] (ServerService Thread Pool -- 10) WFLYUT0021: Registered web context: / 2016-06-27 22:21:49,457 INFO [org.jboss.as.server] (main) WFLYSRV0010: Deployed "nosql-microservices.war" (runtime-name : "nosql-microservices.war") |
Agora o aplicativo pode ser acessado como:
|
1 |
curl https://localhost:8080/webresources/airline |
E a saída formatada é semelhante:
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
[ { "travel-sample": { "country": "United States", "iata": "Q5", "callsign": "MILE-AIR", "name": "40-Mile Air", "icao": "MLA", "id": 10, "type": "airline" } }, . . . { "travel-sample": { "country": "France", "iata": "A5", "callsign": "AIRLINAIR", "name": "Airlinair", "icao": "RLA", "id": 1203, "type": "airline" } } ] |
Então você criou um microsserviço simples usando o WildFly Swarm acessando um banco de dados Couchbase em execução como um contêiner do Docker. Agora, idealmente, esse serviço do WildFly Swarm deve ser empacotado como uma imagem do Docker e, em seguida, essa imagem do Docker serviria como o serviço. Um perfil Maven com o nome doca já está adicionado ao pom.xml mas edição #3 está fazendo com que esse cenário fracasse.
