Um guia rápido para o Spring Cloud Consul

Um guia rápido para o Spring Cloud Consul

1. Visão geral

O projetoSpring Cloud Consul fornece fácil integração com o Consul para aplicativos Spring Boot.

Consul é uma ferramenta que fornece componentes para resolver alguns dos desafios mais comuns em uma arquitetura de microsserviços:

  • Descoberta de serviço - para registrar e cancelar o registro automático dos locais de rede das instâncias de serviço

  • Verificação de integridade - para detectar quando uma instância de serviço está em funcionamento

  • Configuração distribuída - para garantir que todas as instâncias de serviço usem a mesma configuração

Neste artigo, veremos como podemos configurar um aplicativo Spring Boot para usar esses recursos.

2. Pré-requisitos

Para começar, é recomendável dar uma olhada rápida emConsule todos os seus recursos.

Neste artigo, vamos usar um agente Consul em execução emlocalhost:8500. Para obter mais detalhes sobre como instalar o Consul e executar um agente, consulte estelink.

Primeiro, precisaremos adicionar a dependênciaspring-cloud-starter-consul-all ao nossopom.xml:


    org.springframework.cloud
    spring-cloud-starter-consul-all
    1.3.0.RELEASE

3. Descoberta de serviço

Vamos escrever nosso primeiro aplicativo Spring Boot e conectar com o agente Consul em execução:

@SpringBootApplication
public class ServiceDiscoveryApplication {

    public static void main(String[] args) {
        new SpringApplicationBuilder(ServiceDiscoveryApplication.class)
          .web(true).run(args);
    }
}

By default, Spring Boot will try to connect to the Consul agent at localhost:8500. Para usar outras configurações, precisamos atualizar o arquivoapplication.yml:

spring:
  cloud:
    consul:
      host: localhost
      port: 8500

Então, se visitarmos o site do agente do Consul no navegador emhttp://localhost:8500, veremos que nosso aplicativo foi devidamente registrado no Consul com o identificador de“$\{spring.application.name}:$\{profiles separated by comma}:$\{server.port}”.

Para personalizar esse identificador, precisamos atualizar a propriedadespring.cloud.discovery.instanceId com outra expressão:

spring:
  application:
    name: myApp
  cloud:
    consul:
      discovery:
        instanceId: ${spring.application.name}:${random.value}

Se executarmos o aplicativo novamente, veremos que ele foi registrado usando o identificador“MyApp” mais um valor aleatório. Precisamos disso para executar várias instâncias de nosso aplicativo em nossa máquina local.

Finalmente,to disable Service Discovery, we need to set the property spring.cloud.consul.discovery.enabled to false.

3.1. Procurando Serviços

Já temos nosso aplicativo registrado no Consul, mas como os clientes podem encontrar os terminais de serviço? Precisamos de um serviço de cliente de descoberta para obter um serviço em execução e disponível no Consul.

Spring provides a DiscoveryClient API for this, que podemos habilitar com a anotação@EnableDiscoveryClient:

@SpringBootApplication
@EnableDiscoveryClient
public class DiscoveryClientApplication {
    // ...
}

Então, podemos injetar o beanDiscoveryClient em nosso controlador e acessar as instâncias:

@RestController
public class DiscoveryClientController {

    @Autowired
    private DiscoveryClient discoveryClient;

    public Optional serviceUrl() {
        return discoveryClient.getInstances("myApp")
          .stream()
          .map(si -> si.getUri());
          .findFirst()
    }
}

Por fim, definiremos nossos endpoints de aplicativo:

@GetMapping("/discoveryClient")
public String discoveryPing() throws RestClientException,
  ServiceUnavailableException {
    URI service = serviceUrl()
      .map(s -> s.resolve("/ping"))
      .orElseThrow(ServiceUnavailableException::new);
    return restTemplate.getForEntity(service, String.class)
      .getBody();
}

@GetMapping("/ping")
public String ping() {
    return "pong";
}

O caminho“myApp/ping” é o nome do aplicativo Spring com o terminal em serviço. A Consul fornecerá todos os aplicativos disponíveis chamados“myApp”.

4. Verificação de saúde

O Consul verifica periodicamente a integridade dos pontos de extremidade do serviço.

Por padrão,Spring implements the health endpoint to return 200 OK if the app is up. Se quisermos personalizar o endpoint, temos que atualizar oapplication.yml:

spring:
  cloud:
    consul:
      discovery:
        healthCheckPath: /my-health-check
        healthCheckInterval: 20s

Como resultado, o Consul pesquisará o endpoint“/my-health-check” a cada 20 segundos.

Vamos definir nosso serviço de verificação de integridade personalizado para retornar um statusFORBIDDEN:

@GetMapping("/my-health-check")
public ResponseEntity myCustomCheck() {
    String message = "Testing my healh check function";
    return new ResponseEntity<>(message, HttpStatus.FORBIDDEN);
}

Se formos para o site do agente Consul, veremos que nosso aplicativo está falhando. Para corrigir isso, o serviço“/my-health-check” deve retornar o código de status HTTP200 OK.

5. Configuração Distribuída

Este recursoallows synchronizing the configuration among all the services. O Cônsul observará as alterações na configuração e acionará a atualização de todos os serviços.

Primeiro, precisamos adicionar a dependênciaspring-cloud-starter-consul-config ao nossopom.xml:


    org.springframework.cloud
    spring-cloud-starter-consul-config
    1.3.0.RELEASE

Também precisamos mover as configurações do Consul e do nome do aplicativo Spring do arquivoapplication.yml para o arquivobootstrap.yml que o Spring carrega primeiro.

Em seguida, precisamos ativar o Spring Cloud Consul Config:

spring:
  application:
    name: myApp
  cloud:
    consul:
      host: localhost
      port: 8500
      config:
        enabled: true

O Spring Cloud Consul Config procurará as propriedades no Consul em“/config/myApp”. Portanto, se tivermos uma propriedade chamada“my.prop”, precisaremos criar essa propriedade no site do agente do Consul.

Podemos criar a propriedade indo para a seção“KEY/VALUE” e inserindo“/config/myApp/my/prop” no formulário“Create Key”e“Hello World” como valor. Por fim, clique no botão“Create”.

Lembre-se de que, se estivermos usando perfis do Spring, precisamos anexar os perfis ao lado do nome do aplicativo Spring. Por exemplo, se estivermos usando o perfildev, o caminho final no Consul será“/config/myApp,dev”.

Agora, vamos ver a aparência do nosso controlador com as propriedades injetadas:

@RestController
public class DistributedPropertiesController {

    @Value("${my.prop}")
    String value;

    @Autowired
    private MyProperties properties;

    @GetMapping("/getConfigFromValue")
    public String getConfigFromValue() {
        return value;
    }

    @GetMapping("/getConfigFromProperty")
    public String getConfigFromProperty() {
        return properties.getProp();
    }
}

E a classeMyProperties:

@RefreshScope
@Configuration
@ConfigurationProperties("my")
public class MyProperties {
    private String prop;

    // standard getter, setter
}

Se executarmos o aplicativo, os camposvalueeproperties têm o mesmo valor“Hello World” do Consul.

5.1. Atualizando a configuração

Que tal atualizar a configuração sem reiniciar o aplicativo Spring Boot?

Se voltarmos ao site do agente Consul e atualizarmos a propriedade“/config/myApp/my/prop” com outro valor como“New Hello World”, o campovalue não mudará e o campoproperties terá foi atualizado para“New Hello World” conforme esperado.

Isso ocorre porque o campoproperties é uma classeMyProperties que possui a anotação@RefreshScope. All beans annotated with the @RefreshScope annotation will be refreshed after configuration changes.

Na vida real, não devemos ter as propriedades diretamente no Consul, mas devemos armazená-las persistentemente em algum lugar. Podemos fazer isso usando umConfig Server.

6. Conclusão

Neste artigo, vimos como configurar nossos aplicativos Spring Boot para funcionar com o Consul para fins de Service Discovery, personalizar as regras de verificação de integridade e compartilhar uma configuração distribuída.

Também introduzimos uma série de abordagens para os clientes invocarem esses serviços registrados.

Como de costume, as fontes podem ser encontradasover on GitHub.