Desenvolvendo microsserviços com Spring Cloud Netflix

Neste post, iremos abordar conceitos e desenvolver um exemplo de aplicação usando Service Discovery com Spring e Netflix OSS.

Por JAMILA PERIPOLLI SOUZA

 

Microsserviços se tornam cada dia mais populares por prometerem maior resiliência, melhor escalabilidade e uma série de outros benefícios. Porém, como todos sabem, grandes poderes trazem grandes responsabilidades. Este é o primeiro post de uma série sobre utilização das tecnologias Netflix OSS com Spring Cloud para solucionar de maneira fácil e rápida os novos desafios que essa arquitetura traz para o desenvolvimento e operação de software.

 

O que é Service Discovery?

 

Em uma aplicação moderna que utiliza a arquitetura de microserviços, geralmente a comunicação entre os serviços é feita através de APIs REST.  Neste modelo, também é comum a aplicação ser disponibilizada em nuvem, o que permite a criação de instâncias dinamicamente levando em consideração novos deploys, escalabilidade e possíveis falhas.

 

Nesse cenário, o conceito de Service Discovery consiste em obter de maneira dinâmica os endereços de IP dos serviços que iremos consumir.

 

Para que isso ocorra haverá comunicação entre três componentes:

 

  • Service Provider – Fornecerá o serviço e está sujeito a mudança de endereço.
  • Service Consumer – Consumirá o serviço e precisa conhecer o endereço que será chamado.
  • Service Registry – Mantém o endereço atualizado de todas as instâncias dos serviços.

 

Por que utilizar o Eureka?

 

Eureka é uma solução de Service Discovery open source desenvolvida pela Netflix e é composta pelos módulos Eureka Server e Eureka Client.  

 

  • O Eureka Server consiste em uma aplicação que atua como Service Registry permitindo que outras aplicações registrem suas instâncias, com isso,  ele controla os endereços registrados mantendo-os atualizados e sinalizando quando um serviço não está disponível.
  • O Eureka Client é um componente Java que facilita a interação com Eureka Server.

 

Dentre as vantagens de se utilizar o Eureka estão:

 

  • É otimizado para trabalhar em AWS clouds com diferentes regiões;
  • O Eureka Client possui um serviço básico de load-balancing que utiliza a estratégia round-robin e pode ser utilizado quando não se deseja expor o serviço para o usuário final.
  • Clients não escritos em Java podem se comunicar com o Eureka Server através de uma API REST.

 

Mão na massa

 

O Spring Framework possui uma biblioteca específica que encapsula várias tecnologias Netflix OSS, dentre elas o Eureka. Isso permite com que aplicações Eureka Server e Eureka Client sejam construídas de maneira muito mais fácil e intuitiva utilizando configurações baseadas em annotations.

 

Eureka Server

 

O primeiro passo para implementar o Service Discovery com Spring Cloud Netflix é construir um Eureka Server, para isso podemos criar uma aplicação Spring Boot através do Spring Initializr.

 

spring-netflix-oss

 

Observe que já é possível adicionar a dependência do Eureka Server automaticamente, mas, para quem não o fizer, basta adicionar no pom.xml (em caso de projetos Maven).

 

<dependency>
   <groupId>org.springframework.cloud</groupId>
   <artifactId>spring-cloud-starter-netflix-eureka-server</artifactId>
</dependency>

 

Ou no build.gradle (em caso de projetos Gradle).

 

compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-server')

 

Após a criação do projeto, na classe que inicializa a aplicação (main) adicione a anotação @EnableEurekaServer.

 

@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}

 

Com isso, a aplicação já está pronta para rodar, porém, é interessante incluir algumas configurações no arquivo de propriedades application.yml, como a porta que será utilizada e desabilitar o Eureka Client, para que nosso server não se auto-registre.

 

server:

 port: 8761
eureka:

 client:
   registerWithEureka: false
   fetchRegistry: false

 

Para rodar a aplicação basta compilar e executar a classe principal, ou se preferir, utilizar os comandos Maven ou Gradle de acordo com sua preferência.

 

Após a inicialização acesse http://localhost:8761 e você deve ver uma página como esta:

 

spring-netflix-oss

 

Eureka Client – Service Provider

 

Agora que nosso Eureka Server está pronto, vamos criar uma aplicação Eureka Client capaz de se registrar em nosso server e disponibilizar um serviço de saudações através de um endpoint, para isso, utilizaremos novamente o Spring Initializr.

 

spring-netflix-oss

 

Note dessa vez que será preciso adicionar a dependência Eureka Discovery, esta permite que a aplicação se registre utilizando o Eureka Client.

Maven:

 

<dependency>

<groupId>org.springframework.cloud</groupId>

<artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>

</dependency>

 

Gradle:

 

compile('org.springframework.cloud:spring-cloud-starter-netflix-eureka-client')

 

Após a criação do projeto, desta vez vamos adicionar a anotação @EnableDiscoveryClient na classe principal.

 

@SpringBootApplication

@EnableDiscoveryClient

public class GreetingServiceApplication {

public static void main(String[] args) {

SpringApplication.run(GreetingServiceApplication.class, args);

}

}

Em seguida vamos adicionar ao application.yml as seguintes propriedades:

 

spring:

 application:

   name: greeting-service

server:

 port: 8080

eureka:

 client:

   serviceUrl:

     defaultZone: http://localhost:8761/eureka

 

O valor configurado no spring.application.name, será utilizado pelo Eureka como o nome do serviço registrado, o server.port é a configuração da porta onde será disponibilizada a aplicação e o eureka.client.serviceUrl.defaultZone refere-se à URL do Eureka Server no qual a aplicação deverá se registrar.

 

Após essas alterações, nossa aplicação já está pronta para ser executada registrando-se em nosso Eureka Server.

 

Executando a aplicação poderá confirmar verificando a instância registrada na página do Eureka Server.

 

spring-netflix-oss

 

Com a aplicação registrada no Eureka, vamos criar uma classe para prover saudações randomicamente.

 

@Service

public class GreetingService {



   private final List<String> greetings = Arrays.asList("Hi", "Hello", "Hey");



   public String getGreeting() {

       Random random = new Random();

       int randomIndex = random.nextInt(greetings.size());

       return greetings.get(randomIndex);

   }



}

 

O próximo passo é criar um RestController com um endpoint que retorne saudações. Utilizaremos as anotações do Spring @RequestMapping(“/greeting”) para definir o path do endpoint como “/greeting” e @GetMapping para definir que o método greet responderá às requisições que utilizam o método HTTP GET.

 

@RestController

@RequestMapping("/greeting")

public class GreetingController {

   @Autowired

   private GreetingService service;



   @GetMapping

   public String greet() {

       return service.getGreeting();

   }



}

 

Ao finalizar esta etapa a aplicação service-provider está pronta. Ao iniciar a aplicação e acessar http://localhost:8080/greeting deve-se obter “Hi”, “Hello” ou “Hey” como resposta.

Eureka Client – Service Consumer

 

Agora vamos construir uma aplicação que consuma o serviço de saudações criado anteriormente utilizando uma instância registrada no Eureka.

O primeiro passo, será  criar uma nova aplicação Eureka Client e realizar as configurações para que ela se registre no Eureka Server (caso tenha dúvida, consulte o passo Eureka Client – Service Provider).

 

Após as configurações, utilizaremos a classe DiscoveryClient para obter instâncias registradas no eureka utilizando o serviceId do serviço que queremos consumir. O serviceId é o nome utilizado pelo serviço para se registrar no Eureka.

 

@Service

public class EurekaService {



   @Autowired

   private DiscoveryClient discoveryClient;



   public URI getInstance(String serviceId) {

       List<ServiceInstance> instances = discoveryClient.getInstances(serviceId);

       if(instances != null && !instances.isEmpty()) {

           return instances.get(0).getUri();

       }

       return null;

   }

}

 

Para consumir o serviço, basta utilizar a URI retornada no método getInstance(serviceId) juntamente com o path do endpoint que desejamos chamar.

 

É importante lembrar que o serviceId utilizado é “greeting-service”.

 

@Component
public class GreetingConsumer {

    @Autowired
    private RestTemplate restTemplate;

    @Autowired
    private EurekaService eurekaService;

    @Value("${app.greetingService.serviceId}")
    private String greetingServiceId;

    @Value("${app.greetingService.endpoint.greeting}")
    private String greetingEndpointUri;

    
   public String getRandomGreeting() {
        URI uri = eurekaService.getInstance(greetingServiceId);
        String greeting = restTemplate.getForObject(uri.toString() + greetingEndpointUri, String.class);
        return greeting;
    }

 

Conclusão

 

O Eureka é uma das opções de Service Discovery mais utilizadas atualmente. Agora que você já sabe o que é Service Discovery, como configurar um Eureka Server, registrar aplicações com o Eureka Client e obter instâncias de serviços dinamicamente, não esqueça de conferir o próximo post da série onde falaremos sobre Client-side Load Balancing.

 

Os projetos criados estão disponíveis no Github e serão utilizados nos próximos posts da série.

 

Eureka Serverhttps://github.com/JamilaPeripolli/eureka-server

 

Eureka Client (Provider)https://github.com/JamilaPeripolli/greeting-service (branch eureka-client)

 

Eureka Client (Consumer)https://github.com/JamilaPeripolli/user-greeting-service (branch eureka-client)

 

Para mais informações e opções de configuração, acesse a wiki do Eureka no Github.

 

Para saber mais sobre a arquitetura de microsserviços, leia este artigo de Martin Fowler e James Lewis.

 

Até a próxima!

Por JAMILA PERIPOLLI SOUZA

Pós graduanda em desenvolvimento para web, móveis e embarcados pelo IFPR. Desenvolve com foco em back-end. Adora aprender coisas novas (qualquer tipo de coisa).

Postado em: 22 de junho de 2018

Confira outros artigos do nosso blog

Inteligência Artificial: uma introdução ao Deep Learning

11 de setembro de 2018

Guilherme Moraes Armigliatto

Implementando Circuit Breaker com Spring Cloud Netflix

25 de julho de 2018

Jamila Peripolli Souza

Balanceamento de carga em microsserviços com Spring Cloud Netflix

13 de julho de 2018

Jamila Peripolli Souza

Quais os benefícios da arquitetura REST?

26 de junho de 2018

Henrique Lacerda

Deixe seu comentário