Arquitetura de microsserviços: implemente localmente com Java, Spring e MongoDB
Maxime Beugnet4 min read • Published Aug 29, 2024 • Updated Aug 29, 2024
APLICATIVO COMPLETO
Avalie esse Tutorial
"Os microsserviços são incríveis, e os aplicativos monométricos são malévolos."
Se você está lendo este artigo, você já o leu um milhão de vezes, e não serei eu que lhe direi o contrário!
Neste post, criaremos uma arquitetura de microsserviços usando o MongoDB.
O código fonte está disponível nestes dois repositórios.
1 git clone git@github.com:mongodb-developer/microservices-architecture-mongodb.git 2 git clone git@github.com:mongodb-developer/microservices-architecture-mongodb-config-repo.git
Vamos usar as dependências Spring Boot e Spring Cloud para construir nossa arquitetura.
Precisamos de vários serviços para executar este projeto. Vamos falar sobre eles um por um.
Ao ler esta publicação, sugerimos que siga as instruções no arquivoREADME.md e inicie o serviço relacionado a cada seção.
O primeiro serviço de que precisamos é de um servidor de configuração.
Esse serviço nos permite armazenar todos os arquivos de configuração de nossos microsserviços em um único repositório, para que nossas configurações sejam fáceis de versionar e armazenar.
A configuração do nosso servidor de configuração é simples e direta ao ponto:
1 spring.application.name=config-server 2 server.port=8888 3 spring.cloud.config.server.git.uri=${HOME}/Work/microservices-architecture-mongodb-config-repo 4 spring.cloud.config.label=main
Ele nos permite localizar o repositório git que armazena nossa configuração de microsserviços e a ramificação que deve ser usada.
Observe que o único "truque" de que você precisa em seu projeto Spring Boot para iniciar um servidor de configuração é a anotação
@EnableConfigServer
.1 package com.mongodb.configserver; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 import org.springframework.cloud.config.server.EnableConfigServer; 6 7 8 9 public class ConfigServerApplication { 10 public static void main(String[] args) { 11 SpringApplication.run(ConfigServerApplication.class, args); 12 } 13 }
Um registro de serviço é como uma lista telefônica para microsserviços. Ele monitora quais microsserviços estão em execução e onde estão localizados (endereço IP e porta). Outros serviços podem pesquisar essas informações para encontrar e se comunicar com os microsserviços de que precisam.
Um registro de serviço é útil porque permite o balanceamento de carga no lado do cliente e separa os provedores de serviços dos consumidores sem a necessidade de DNS.
Novamente, você não precisa de muito para poder iniciar um registro do serviço Spring Boot. A anotação
@EnableEurekaServer
faz toda a mágica acontecer.1 package com.mongodb.serviceregistry; 2 3 import org.springframework.boot.SpringApplication; 4 import org.springframework.boot.autoconfigure.SpringBootApplication; 5 import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer; 6 7 8 9 public class ServiceRegistryApplication { 10 public static void main(String[] args) { 11 SpringApplication.run(ServiceRegistryApplication.class, args); 12 } 13 }
A configuração também vai ao ponto:
1 spring.application.name=service-registry 2 server.port=8761 3 eureka.client.register-with-eureka=false 4 eureka.client.fetch-registry=false
As duas últimas linhas impedem que o registro de serviço se registre para si mesmo e recupere o registro de si mesmo.
O serviço de gateway de API nos permite ter um único ponto de entrada para acessar todos os nossos microsserviços. É claro que você deve ter mais de um em produção, mas todos eles poderão se comunicar com todos os microsserviços e distribuir a carga de trabalho uniformemente balanceando a carga das consultas em seu pool de microsserviços.
Além disso, um gateway de API é útil para abordar preocupações transversais, como segurança, monitoramento, coleta de métricas e resiliência.
Quando nossos microsserviços são iniciados, eles se registram no registro de serviços. O gateway de API pode usar esse registro para localizar os microsserviços e distribuir as queries de acordo com sua configuração de roteamento.
1 server: 2 port: 8080 3 4 spring: 5 application: 6 name: api-gateway 7 cloud: 8 gateway: 9 routes: 10 - id: company-service 11 uri: lb://company-service 12 predicates: 13 - Path=/api/company/**,/api/companies 14 - id: employee-service 15 uri: lb://employee-service 16 predicates: 17 - Path=/api/employee/**,/api/employees 18 19 eureka: 20 client: 21 register-with-eureka: true 22 fetch-registry: true 23 service-url: 24 defaultZone: http://localhost:8761/eureka/ 25 instance: 26 hostname: localhost
Observe que nosso gateway de API é executado na porta 8080.
Finalmente, temos nossos microsserviços MongoDB.
Os microsserviços devem ser independentes uns dos outros. Por esse motivo, precisamos de duas instâncias do MongoDB: uma para cada microsserviço.
Observe que, nos arquivos de configuração dos serviços da empresa e do funcionário, eles estão sendo executados, respectivamente, nas portas 8081 e 8082.
1 spring.data.mongodb.uri=${MONGODB_URI_1:mongodb://localhost:27017} 2 spring.threads.virtual.enabled=true 3 management.endpoints.web.exposure.include=* 4 management.info.env.enabled=true 5 info.app.name=Company Microservice 6 info.app.java.version=21 7 info.app.type=Spring Boot 8 server.port=8081 9 eureka.client.register-with-eureka=true 10 eureka.client.fetch-registry=true 11 eureka.client.service-url.defaultZone=http://localhost:8761/eureka/ 12 eureka.instance.hostname=localhost
1 spring.data.mongodb.uri=${MONGODB_URI_2:mongodb://localhost:27018} 2 spring.threads.virtual.enabled=true 3 management.endpoints.web.exposure.include=* 4 management.info.env.enabled=true 5 info.app.name=Employee Microservice 6 info.app.java.version=21 7 info.app.type=Spring Boot 8 server.port=8082 9 eureka.client.register-with-eureka=true 10 eureka.client.fetch-registry=true 11 eureka.client.service-url.defaultZone=http://localhost:8761/eureka/ 12 eureka.instance.hostname=localhost
Observe que os dois microsserviços estão conectados a dois clusters MongoDB diferentes para manter sua dependência. O serviço da empresa está usando o nó do MongoDB na porta 27017 e o serviço do funcionário está na porta 27018.
Naturalmente, isso é somente se você estiver executando tudo localmente. Na produção, eu recomendamos usar dois clusters no MongoDB Atlas. Você pode substituir o URI MongoDB pelas variáveis de ambiente (consulte README.md).
Neste ponto, você deve ter cinco serviços em execução:
- Um servidor de configuração na porta 8888
- Um registro de serviço na porta 8761
- Um gateway de API na porta 8080
- Dois microsserviços:
- serviço de empresa na porta 8081
- serviço de funcionário na porta 8082
E dois nós do MongoDB nas portas 27017 e 27018 ou dois clusters do MongoDB no MongoDB Atlas.
1 DELETE Companies 2 2 3 DELETE Employees 4 2 5 6 POST Company 'MongoDB' 7 POST Company 'Google' 8 9 GET Company 'MongoDB' by 'id' 10 { 11 "id": "661aac7904e1bf066ee8e214", 12 "name": "MongoDB", 13 "headquarters": "New York", 14 "created": "2009-02-11T00:00:00.000+00:00" 15 } 16 17 GET Company 'Google' by 'name' 18 { 19 "id": "661aac7904e1bf066ee8e216", 20 "name": "Google", 21 "headquarters": "Mountain View", 22 "created": "1998-09-04T00:00:00.000+00:00" 23 } 24 25 GET Companies 26 [ 27 { 28 "id": "661aac7904e1bf066ee8e214", 29 "name": "MongoDB", 30 "headquarters": "New York", 31 "created": "2009-02-11T00:00:00.000+00:00" 32 }, 33 { 34 "id": "661aac7904e1bf066ee8e216", 35 "name": "Google", 36 "headquarters": "Mountain View", 37 "created": "1998-09-04T00:00:00.000+00:00" 38 } 39 ] 40 41 POST Employee Maxime 42 POST Employee Tim 43 44 GET Employee 'Maxime' by 'id' 45 { 46 "id": "661aac79cf04401110c03516", 47 "firstName": "Maxime", 48 "lastName": "Beugnet", 49 "company": "Google", 50 "headquarters": "Mountain View", 51 "created": "1998-09-04T00:00:00.000+00:00", 52 "joined": "2018-02-12T00:00:00.000+00:00", 53 "salary": 2468 54 } 55 56 GET Employee 'Tim' by 'id' 57 { 58 "id": "661aac79cf04401110c03518", 59 "firstName": "Tim", 60 "lastName": "Kelly", 61 "company": "MongoDB", 62 "headquarters": "New York", 63 "created": "2009-02-11T00:00:00.000+00:00", 64 "joined": "2023-08-23T00:00:00.000+00:00", 65 "salary": 13579 66 } 67 68 GET Employees 69 [ 70 { 71 "id": "661aac79cf04401110c03516", 72 "firstName": "Maxime", 73 "lastName": "Beugnet", 74 "company": "Google", 75 "headquarters": "Mountain View", 76 "created": "1998-09-04T00:00:00.000+00:00", 77 "joined": "2018-02-12T00:00:00.000+00:00", 78 "salary": 2468 79 }, 80 { 81 "id": "661aac79cf04401110c03518", 82 "firstName": "Tim", 83 "lastName": "Kelly", 84 "company": "MongoDB", 85 "headquarters": "New York", 86 "created": "2009-02-11T00:00:00.000+00:00", 87 "joined": "2023-08-23T00:00:00.000+00:00", 88 "salary": 13579 89 } 90 ]
Observe que o serviço de funcionário envia consultas ao serviço da empresa para recuperar os detalhes da empresa dos funcionários.
Isso confirma que o registro de serviço está fazendo seu trabalho corretamente porque a URL contém apenas uma referência ao microsserviço da empresa, não a seu IP e porta diretos.
1 private CompanyDTO getCompany(String company) { 2 String url = "http://company-service/api/company/name/"; 3 CompanyDTO companyDTO = restTemplate.getForObject(url + company, CompanyDTO.class); 4 if (companyDTO == null) { 5 throw new EntityNotFoundException("Company not found: ", company); 6 } 7 return companyDTO; 8 }
E voilà! Agora você tem uma arquitetura básica de microsserviço em execução que é fácil de usar para iniciar seu projeto.
Nessa arquitetura, pudemos integrar perfeitamente recursos adicionais para melhorar o desempenho e a capacidade de manutenção na produção. O cache seria essencial, especialmente com um número potencialmente grande de funcionários na mesma empresa, aliviando significativamente a carga do serviço da empresa.
A adição de um disjuntor Spring Cloud também poderia melhorar a resiliência na produção e um Spring Cloud Sleuth ajudaria no rastreamento distribuído e na configuração automática.
Em caso de dúvidas, acesse nosso website da comunidade de desenvolvedores, no qual os engenheiros do MongoDB e a MongoDB Community ajudarão você a colocar em prática sua próxima grande ideia com o MongoDB.
Principais comentários nos fóruns
Ainda não há comentários sobre este artigo.
Relacionado
Tutorial
Armazenamento de mídia contínuo: integrando o armazenamento de Blobs do Azure e o MongoDB com o Spring Boot
Nov 05, 2024 | 9 min read