Introdução ao Spring Cloud Netflix - Eureka
1. Visão geral
Neste tutorial, apresentaremos a descoberta declient-side service via “Spring Cloud Netflix Eureka“.
Client-side service discovery allows services to find and communicate with each other without hard-coding hostname and port. O único 'ponto fixo' em tal arquitetura consiste em umservice registry com o qual cada serviço deve se registrar.
Uma desvantagem é que todos os clientes devem implementar uma certa lógica para interagir com esse ponto fixo. Isso pressupõe uma viagem de ida e volta à rede adicional antes da solicitação real.
Com o Netflix Eureka, cada cliente pode agir simultaneamente como servidor, para replicar seu status para um ponto conectado. Em outras palavras, um cliente recupera uma lista de todos os pares conectados de umservice registrye faz todas as solicitações adicionais a quaisquer outros serviços por meio de um algoritmo de balanceamento de carga.
Para serem informados sobre a presença de um cliente, eles precisam enviar um sinal de pulsação ao registro.
Para atingir o objetivo deste artigo, implementaremos trêsmicroservices:
-
aservice registry (Eureka Server),
-
um serviçoREST que se registra no registro (Eureka Client) e
-
um aplicativo da web que está consumindo o serviçoREST como um cliente com reconhecimento de registro (Spring Cloud Netflix *Feign Client*)
== Leitura adicional:
Um guia para o Spring Cloud Netflix - Hystrix
O artigo mostra como configurar um fallback na lógica do aplicativo, usando o Spring Cloud Hystrix.
REST de primavera com um proxy Zuul
Explorando o uso do proxy Zuul para uma API REST Spring, contornando o CORS e a restrição de política de mesma origem do navegador.
2. Eureka Server
Implementar umEureka Server para registro de serviço é tão fácil quanto:
-
adicionandospring-cloud-starter-netflix-eureka-server às dependências
-
habilite o servidor Eureka em@SpringBootApplication anotando-o com@EnableEurekaServer
-
configurar algumas propriedades
Mas vamos fazer isso passo a passo.
Em primeiro lugar, criaremos um novo projeto Maven e colocaremos as dependências nele. Você deve observar que estamos importandospring-cloud-starter-parent para todos os projetos descritos neste tutorial:
org.springframework.cloud
spring-cloud-starter-netflix-eureka-server
org.springframework.cloud
spring-cloud-starter-parent
Greenwich.RELEASE
pom
import
Nota: podemos verificar os últimos lançamentos do Spring Cloud emthe Spring’s Projects documentation.
A seguir, estamos criando a classe principal do aplicativo:
@SpringBootApplication
@EnableEurekaServer
public class EurekaServerApplication {
public static void main(String[] args) {
SpringApplication.run(EurekaServerApplication.class, args);
}
}
Por fim, estamos configurando as propriedades no formatoYAML; então, umapplication.yml será nosso arquivo de configuração:
server:
port: 8761
eureka:
client:
registerWithEureka: false
fetchRegistry: false
Here we’re configuring an application port – 8761 is the default one for Eureka servers. Estamos dizendo aoEureka Client integrado para não se registrar com 'ele mesmo' porque nosso aplicativo deve estar atuando como um servidor.
Agora vamos apontar nosso navegador parahttp://localhost:8761 para visualizar o painel deEureka, onde mais tarde iremos inspecionar as instâncias registradas.
No momento, vemos indicadores básicos, como status e saúde.
3. Cliente Eureka
Para que@SpringBootApplication esteja ciente da descoberta, devemos incluir algunsSpring Discovery Client (por exemplospring-cloud-starter-netflix-eureka-client) em nossoclasspath.
Então, precisamos anotar a@Configuration com@EnableDiscoveryClient ou@EnableEurekaClient –, observar que essa anotação é opcional se tivermos a dependênciaspring-cloud-starter-netflix-eureka-client do caminho de classe.
O último diz aSpring Boot para usar o Spring Netflix Eureka explicitamente para descoberta de serviço. Para preencher nosso aplicativo cliente com alguma vida de amostra, também incluiremos o pacotespring-boot-starter-web empom.xmle implementar um controladorREST.
Mas primeiro, vamos adicionar as dependências. Novamente, podemos deixar para a dependência despring-cloud-starter-parent descobrir as versões do artefato para nós:
org.springframework.cloud
spring-cloud-starter-netflix-eureka-starter
org.springframework.boot
spring-boot-starter-web
Aqui vamos implementar a classe principal do aplicativo:
@SpringBootApplication
@RestController
public class EurekaClientApplication implements GreetingController {
@Autowired
@Lazy
private EurekaClient eurekaClient;
@Value("${spring.application.name}")
private String appName;
public static void main(String[] args) {
SpringApplication.run(EurekaClientApplication.class, args);
}
@Override
public String greeting() {
return String.format(
"Hello from '%s'!", eurekaClient.getApplication(appName).getName());
}
}
E a interfaceGreetingController:
public interface GreetingController {
@RequestMapping("/greeting")
String greeting();
}
Aqui, em vez da interface, também podemos simplesmente declarar o mapeamento dentro da classeEurekaClientApplication. A interface pode ser útil se quisermos compartilhá-la entre servidor e cliente.
Em seguida, temos que configurar umapplication.yml com um nome de aplicativoSpring configurado para identificar exclusivamente nosso cliente na lista de aplicativos registrados.
Podemos deixarSpring Boot escolher uma porta aleatória para nós porque mais tarde estaremos acessando este serviço com o seu nome.
Por fim, precisamos informar ao cliente onde ele deve localizar o registro:
spring:
application:
name: spring-cloud-eureka-client
server:
port: 0
eureka:
client:
serviceUrl:
defaultZone: ${EUREKA_URI:http://localhost:8761/eureka}
instance:
preferIpAddress: true
Quando decidimos configurar nosso cliente Eureka dessa maneira, tínhamos em mente que esse tipo de serviço deveria ser mais facilmente escalável.
Agora iremos executar o cliente e apontar nosso navegador parahttp://localhost:8761 novamente, para ver seu status de registro no painel Eureka. Ao usar o Painel, podemos fazer outras configurações, por exemplo vincule a página inicial de um cliente registrado ao Painel para fins administrativos. As opções de configuração, no entanto, estão além do escopo deste artigo.
4. Cliente fingir
Para finalizar nosso projeto com três microsserviços dependentes, agora implementaremos um aplicativo da web que consomeREST usandoSpring Netflix Feign Client.
Pense emFeign comoSpring RestTemplate com reconhecimento de descoberta usando interfaces para se comunicar com terminais. Essas interfaces serão implementadas automaticamente em tempo de execução e, em vez deservice-urls, está usandoservice-names.
SemFeign, teríamos que autowire uma instância deEurekaClient em nosso controlador com o qual poderíamos receber uma informação de serviço porservice-name como um objetoApplication.
Usaríamos esteApplication para obter uma lista de todas as instâncias deste serviço, escolher um adequado e usar esteInstanceInfo para obter o nome do host e a porta. Com isso, poderíamos fazer uma solicitação padrão com qualquerhttp client.
Por exemplo:
@Autowired
private EurekaClient eurekaClient;
public void doRequest() {
Application application =
eurekaClient.getApplication("spring-cloud-eureka-client");
InstanceInfo instanceInfo = application.getInstances().get(0);
String hostname = instanceInfo.getHostName();
int port = instanceInfo.getPort();
// ...
}
UmRestTemplate também pode ser usado para acessarEureka serviços do cliente por nome, mas este tópico está além deste artigo.
Para configurar nosso projetoFeign Client, vamos adicionar as quatro dependências a seguir ao seupom.xml:
org.springframework.cloud
spring-cloud-starter-feign
org.springframework.cloud
spring-cloud-starter-netflix-eureka-client
org.springframework.boot
spring-boot-starter-web
org.springframework.boot
spring-boot-starter-thymeleaf
OFeign Client está localizado no pacotespring-cloud-starter-feign. Para habilitá-lo, temos que anotar a@Configuration com@EnableFeignClients. Para usá-lo, simplesmente anotamos uma interface com@FeignClient(“service-name”)e conectamos automaticamente a um controlador.
Um bom método para criar essesFeignClients é criar interfaces com métodos anotados@RequestMapping e colocá-los em um módulo separado. Dessa forma, eles podem ser compartilhados entre servidor e cliente. No lado do servidor, você pode implementá-los como@Controller, e no lado do cliente, eles podem ser estendidos e anotados como@FeignClient.
Além disso, ospring-cloud-starter-eureka package precisa ser incluído no projeto e ativado anotando a classe do aplicativo principal com@EnableEurekaClient.
As dependênciasspring-boot-starter-webespring-boot-starter-thymeleaf são usadas parapresent a view, contendo dados buscados de nosso serviçoREST.
Esta será a nossa interfaceFeign Client:
@FeignClient("spring-cloud-eureka-client")
public interface GreetingClient {
@RequestMapping("/greeting")
String greeting();
}
Aqui vamos implementar a classe principal do aplicativo que atua simultaneamente como um controlador:
@SpringBootApplication
@EnableFeignClients
@Controller
public class FeignClientApplication {
@Autowired
private GreetingClient greetingClient;
public static void main(String[] args) {
SpringApplication.run(FeignClientApplication.class, args);
}
@RequestMapping("/get-greeting")
public String greeting(Model model) {
model.addAttribute("greeting", greetingClient.greeting());
return "greeting-view";
}
}
Este será o modelo HTML para nossa visão:
Greeting Page
Pelo menos o arquivo de configuraçãoapplication.yml é quase o mesmo da etapa anterior:
spring:
application:
name: spring-cloud-eureka-feign-client
server:
port: 8080
eureka:
client:
serviceUrl:
defaultZone: ${EUREKA_URI:http://localhost:8761/eureka}
Agora podemos criar e executar este serviço. Por fim, apontaremos nosso navegador parahttp://localhost:8080/get-greeting e ele deverá exibir algo como o seguinte:
Hello from SPRING-CLOUD-EUREKA-CLIENT!
5. ‘TransportException: não pode executar a solicitação em nenhum servidor conhecido
Durante a execução do servidor Eureka, geralmente encontramos exceções como:
com.netflix.discovery.shared.transport.TransportException: Cannot execute request on any known server
Basicamente, isso ocorre devido à configuração errada emapplication.properties ouapplication.yml. Eureka fornece duas propriedades para o cliente que podem ser configuradas.
-
registerWithEureka: Se definirmos essa propriedade comotrue, enquanto o servidor inicia, o cliente embutido tentará se registrar no servidor Eureka.
-
fetchRegistry: O cliente embutido tentará obter o registroEureka se configurarmos esta propriedade como verdadeira.
Agorawhen we start up the Eureka server, we don’t want to register the inbuilt client to configure itself with the server.
Se marcarmos as propriedades acima comotrue (ou não as configurarmos comotrue por padrão) ao iniciar o servidor, o cliente embutido tenta se registrar com oEureka servidor e também tenta obter o registro que ainda não está disponível. Como resultado, obtemosTransportException.
Portanto, nunca devemos configurar essas propriedades comotrue nos aplicativos de servidorEureka. As configurações corretas que devem ser colocadas emapplication.yml são fornecidas abaixo:
eureka:
client:
registerWithEureka: false
fetchRegistry: false
6. Conclusão
Como vimos, agora podemos implementar um registro de serviço usandoSpring Netflix Eureka Servere registrar algunsEureka Clients com ele.
Como nossoEureka Client da etapa 3 escuta em uma porta escolhida aleatoriamente, ele não sabe sua localização sem as informações do registro. Com umFeign Cliente nosso registro, podemos localizar e consumir o serviçoREST, mesmo quando a localização muda.
Por fim, temos uma visão geral do uso da descoberta de serviço em uma arquitetura de microsserviço.
Como de costume, você encontrará as fonteson GitHub, que também incluem um conjunto de arquivos relacionados aDocker para usar comdocker-compose para criar contêineres de nosso projeto.