BT

Disseminando conhecimento e inovação em desenvolvimento de software corporativo.

Contribuir

Tópicos

Escolha a região

Início Artigos Microservices na nuvem - Parte 1

Microservices na nuvem - Parte 1

Microservices são uma arquitetura de software, onde o sistema é uma coleção de vários serviços independentes, onde cada um tem um foco comercial específico e se comunica com os outros com um protocolo, independente da linguagem, como o REST. A iniciativa Eclipse MicroProfile otimiza o Enterprise Java para a arquitetura de microservices. É baseado em um subconjunto de APIs do Jakarta EE. Esta postagem fornecerá uma visão geral de algumas práticas recomendadas para trabalhar com microservices Java no Platform.sh.

O contexto

Para comemorar o No Oracle GroundBreakers Tour pela América Latina, criaremos uma arquitetura de microservices com base no contexto das cidades, sessões e palestrantes em que o Oracle GroundBreaker Tour está hospedado.

Oracle Groundbreakers Tour - América Latina

  • Chile
  • Uruguai
  • Argentina
  • Paraguai
  • Brasil
  • Equador
  • Colômbia
  • Panamá
  • Costa Rica
  • México
  • Guatemala
  • Peru

Para gerenciar as conferências na viagem à América Latina, teremos três microservices:

  • Palestrante. O serviço de palestrantes que armazena o nome, biografia e links da mídia social para cada palestrante.
  • Conferência. O serviço de conferência que agrupa as palestras e os respectivos palestrantes, que lida com o nome, cidade e ano da viagem à conferência.
  • Sessão: o serviço de sessão que lida com o nome, título, descrição e informações da conferência e do palestrante.

Bancos de Dados

Cada banco de dados tem sua proposta, estrutura e comportamento específico, portanto, usaremos bancos diferentes de acordo com cada serviço. De fato, essa é a vantagem dos microservices. Cada serviço pode usar uma tecnologia que esteja em conformidade com os requisitos sem afetar os outros. Cada microservice utiliza uma base de dados adequada para o caso de uso especial:

Implementações do Eclipse MicroProfile

A comunidade MicroProfile se dedica a otimizar arquiteturas corporativas em Java baseadas em microservice. Atualmente, a IBM, Red Hat, Tomitribe, Payara, o Java Community Londres (LJC), e SouJava levam o pacote deste grupo.

Unindo as tecnologias

Nosso projeto possui quatro componentes ou implementações de Eclipse MicroProfile:

  • KumuluzEE tratará do microservice Sessão. Os usuários desejam procurar detalhes da sessão, como encontrar sessões que falem sobre o Microprofile Eclipse ou o Jakarta EE. Para trabalhar com esse requisito, o projeto usará um NoSQL que também é um poderoso mecanismo de pesquisa (sim, estamos falando sobre Elasticsearch).
  • O Thorntail manipulará o microservice de palestrantes, o serviço mais simples que gerenciará as informações através do PostgreSQL.
  • O Payara Micro cuidará do microservice da Conferência. Este serviço está fortemente relacionado ao KumuluzEE e ao Thorntail. Para criar uma conferência, precisamos de sessões e palestrantes. O MongoDB parece se encaixar facilmente neste serviço, porque podemos usar o conceito de subdocumentos para colocar uma lista de apresentações e palestrantes na entidade Conference, em vez de estabelecer o relacionamento como em um banco de dados relacional.
  • O Apache TomEE é o navegador do cliente usando HTML 5 como frontend.

Eclipse MicroProfile e Jakarta para o resgate!

Quais são os benefícios significativos do Eclipse MicroProfile? Bem, primeiramente ele usa padrões no Jakarta EE como CDI, JAX-RS e JSON-P.

Para conectar-se ao PostgreSQL ou a qualquer outro banco de dados relacional, existe um JPA específico que descreve o gerenciamento de dados relacionais em aplicações usando a plataforma Java. Para se comunicar com os bancos de dados NoSQL, usaremos a especificação Jakarta NoSQL, que não é a versão final, mas espero que seja lançada em breve.

No lado do cliente, usaremos Eclipse Krazo com uma extensão HTML 5, usando Thymeleaf como o mecanismo de modelo. No momento, o cliente não possui um banco de dados, então se comunicará apenas com os serviços para organizar os valores e os mostrará no navegador. Portanto, usará Eclipse MicroProfile Rest Client, que fornece uma abordagem com segurança tipificada para chamar os serviços RESTful usando HTTP.

Camadas, camadas e mais camadas

O número de camadas em uma aplicação é sempre uma discussão calorosa quando falamos de microservices. As camadas são essenciais para dividir a responsabilidade e escrever um código limpo, já que existem vários padrões para essa abordagem, como o MVC.

No entanto, um grande número de camadas também é difícil de ser mantido, por isso precisamos prestar atenção nas camadas de atraso, que são camadas que servem apenas para chamar outras. Caso contrário, em vez de um MVC, estaremos criando o padrão de cebola, onde iremos chorar toda vez que passarmos por uma camada. Não existe uma fórmula mágica para determinar o número de camadas necessárias. Existe uma preocupação para que as camadas reflitam as ideias de isolamentos das arquiteturas mais limpas.

Em nosso exemplo, temos três camadas:

  • entidade. A primeira instância do negócio e onde o domínio reside. Essas entidades, para as melhores práticas, devem seguir um modelo rico. Podemos fazer essas entidades independentes de um banco de dados, mas desta vez, vamos simplificar e usar a entidade altamente acoplada ao banco.
  • O objeto de transferência de dados (DTO). Apenas uma classe de despejo para permitir a transferência de valores entre o controlador e a entidade. Seu objetivo é impedir que a entidade se torne um modelo anêmico, porque alguns frameworks podem exigir métodos getter e setter para serialização, o que geralmente significa um fraco encapsulamento.
  • O controlador. A ligação entre a view e o model. Apenas manipula o fluxo entre eles. Com pequenas exceções, deve se manter o mais limpo possível, você se lembra da regra de alta coesão, certo?

Existe uma nuvem? Ou apenas é um computador de outra pessoa?

Gerenciar os bancos de dados, o código e as integrações é sempre difícil, mesmo na nuvem. De fato, o servidor ainda está lá e alguém precisa verificá-lo, executar instalações e backups e manter a integridade no geral. Existem boas práticas que ajudar com isso, por exemplo, dentro dos doze fatores requer uma separação estrita da configuração do código.

Felizmente, o Platform.sh fornece um PaaS que gerencia os serviços, como bancos de dados e filas de mensagens, com suporte para várias linguagens, incluindo o Java. Tudo se baseia no conceito de Infraestrutura como Código (IaC), gerenciando e provisionando serviços por meio de arquivos YAML.

Em postagens anteriores, mencionamos como isso é feito no Platform.sh principalmente com três arquivos:

  • um para definir os serviços usados ​​pelos aplicativos (services.yaml).
elasticsearch:
	type: elasticsearch:6.5
	disk: 512
mongodb:
	type: mongodb:3.6
	disk: 512
postgresql:
	type: postgresql:11
	disk: 512
"https://{default}/conferences":
	id: conference
	type: upstream
	upstream: "conference:http"

"https://{default}/sessions":
	id: session
	type: upstream
	upstream: "session:http"

"https://{default}/speakers":
	id: speaker
	type: upstream
	upstream: "speaker:http"

"https://{default}/":
  type: upstream
  upstream: "client:http"

"https://www.{default}/":
  type: redirect
name: client
type: "java:8"

disk: 800

# Os hooks executados em vários pontos do ciclo de vida da aplicação.
hooks:
	build: |
  	mvn -Dhttp.port=8888 -Dspeaker.service=http://speaker.internal/ -Dconference.service=http://conference.internal/ -Dsession.service=http://session.internal/ -DskipTests clean install tomee:exec

relationships:
   speaker: speaker:http
   conference: conference:http
   session: session:http

web:
	commands:
    	start: |
      	mv target/ROOT-exec.jar app/ROOT-exec.jar
      	java -Xmx1024m -jar  app/ROOT-exec.jar

Com os requisitos definidos no arquivo YAML da aplicação, podemos extrair as informações do ambiente. Sim, estamos seguindo os doze fatores que dividem o código da configuração.

echo $PLATFORM_RELATIONSHIPS | base64 --decode | json_pp

{
   "session" : [
  	{
     	"service" : "session",
     	"rel" : "http",
     	"scheme" : "http",
     	"cluster" : "dvtam6qrvyjwi-master-7rqtwti",
     	"port" : 80,
     	"ip" : "169.254.159.17",
     	"host" : "session.internal",
     	"hostname" : "owh4yp4z3tbt3x7fajdexvndpe.session.service._.eu-3.platformsh.site",
     	"type" : "java:8"
  	}
   ],
   "speaker" : [
  	{
     	"scheme" : "http",
     	"rel" : "http",
     	"service" : "speaker",
     	"type" : "java:8",
     	"hostname" : "4edz7hoi7xx4bnb7vkeopzltc4.speaker.service._.eu-3.platformsh.site",
     	"host" : "speaker.internal",
     	"port" : 80,
     	"cluster" : "dvtam6qrvyjwi-master-7rqtwti",
     	"ip" : "169.254.245.54"
  	}
   ],
   "conference" : [
  	{
     	"service" : "conference",
     	"rel" : "http",
     	"scheme" : "http",
     	"port" : 80,
     	"cluster" : "dvtam6qrvyjwi-master-7rqtwti",
     	"ip" : "169.254.81.85",
     	"host" : "conference.internal",
     	"hostname" : "3aora24tymelzobulrvgc5rscm.conference.service._.eu-3.platformsh.site",
     	"type" : "java:8"
  	}
   ]
}

A boa notícia sobre essas informações é que não precisamos manipular ou extrair os dados manualmente, e é por isso que temos o leitor de configuração.

name: conference

type: "java:8"

disk: 800

relationships:
  mongodb: 'mongodb:mongodb'

web:
	commands:
    	start: java -jar -Xmx1024m target/conference-microbundle.jar --port $PORT

Usando o leitor de configuração Java, é possível ler essas configurações e retornar os clientes como MongoDB, Datasource ou Elasticsearch. Por exemplo, no arquivo de configuração do serviço de conferência, precisamos de acesso ao MongoDB, do qual podemos extrair e converter essas informações em uma instância do MongoClient e disponibilizá-las para o CDI.

import com.mongodb.MongoClient;
import jakarta.nosql.document.DocumentCollectionManager;
import org.jnosql.diana.mongodb.document.MongoDBDocumentCollectionManagerFactory;
import org.jnosql.diana.mongodb.document.MongoDBDocumentConfiguration;
import sh.platform.config.Config;
import sh.platform.config.MongoDB;

import javax.enterprise.context.ApplicationScoped;
import javax.enterprise.inject.Produces;

@ApplicationScoped
public class MongoConfig {

	@Produces
	public DocumentCollectionManager getManager() {
    	Config config = new Config();
    	final MongoDB mongo = config.getCredential("mongodb", MongoDB::new);
    	final MongoClient mongoClient = mongo.get();
    	MongoDBDocumentConfiguration configuration = new MongoDBDocumentConfiguration();
    	MongoDBDocumentCollectionManagerFactory factory = configuration.get(mongoClient);
    	return factory.get(mongo.getDatabase());
	}
}

Espera ?! Cadê o código?

Para que este post não se torne um livro, iremos dividi-lo em algumas partes. O primeiro foi uma visão geral sobre as vantagens do uso de microservices, por que devemos usá-los e como o MicroProfileEclipse e o Platform.sh pode nos ajudar nessa empreitada. Existem materiais sobre MicroProfile do Eclipse, JPA, Eclipse Krazo e Eclipse JNoSQL. Caso não se importe com spoilers, confira o código de toda a série no GitHub.

Caso contrário, fique atento para a parte dois, onde veremos o design do código e explicaremos passo a passo.

Sobre o Autor

Otávio é engenheiro de software na Platform.sh, com grande experiência em desenvolvimento open source, com diversas contribuições ao JBoss Weld, Hibernate, Apache Commons e outros projetos. Focado em desenvolvimento poliglota e aplicações de alto desempenho, Otávio trabalhou em grandes projetos nas áreas de finanças, governo, mídias sociais e e-commerce. Membro do comitê executivo do JCP e de vários Expert Groups de JSRs, é também Java Champion e recebeu os prêmios JCP Outstanding Award e Duke's Choice Award.

Avalie esse artigo

Relevância
Estilo/Redação

Conteúdo educacional

BT