Implementação de Cluster Hystrix e Monitoramento com Turbine no Spring Cloud

Este guia aborda a configuração de um cluster Hystrix no Spring Cloud, a integração com o monitor Turbine e a desacoplamento de fallbacks usando Feign, além de ajustes de timeout em ambientes clusterizados.

Configuração do Cluster Hystrix

Para criar um cluster Hystrix, inicie um novo projeto Spring Boot denominado microservico-fornecedor-hystrix-1005. Adicione as seguintes dependências ao arquivo pom.xml:

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>com.exemplo</groupId>
        <artifactId>projeto-spring-cloud</artifactId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <artifactId>microservico-fornecedor-hystrix-1005</artifactId>
    <dependencies>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-data-jpa</artifactId>
        </dependency>
        <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
        </dependency>
        <dependency>
            <groupId>com.alibaba</groupId>
            <artifactId>druid-spring-boot-starter</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
        </dependency>
    </dependencies>
</project>

Configure múltiplos perfis no arquivo application.yml para instâncias em portas diferentes (1004, 1005, 1006), garantindo que o nome do serviço seja consistente. Exemplo para a porta 1005:

servidor:
  porta: 1005
spring:
  datasource:
    tipo: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: com.mysql.jdbc.Driver
    url: jdbc:mysql://localhost:3306/teste?useUnicode=true&characterEncoding=utf8
    usuario: raiz
    senha: raiz
  jpa:
    hibernate:
      ddl-auto: update
    show-sql: true
  aplicacao:
    nome: microservico-aluno
  perfis: fornecedor-hystrix-1005
eureka:
  instancia:
    nome-host: localhost
    nome-app: microservico-aluno
    id-instancia: microservico-aluno:1005
    preferir-endereco-ip: true
  cliente:
    url-servico:
      padrao: http://eureka2001.exemplo.com:2001/eureka/,http://eureka2002.exemplo.com:2002/eureka/,http://eureka2003.exemplo.com:2003/eureka/
hystrix:
  comando:
    padrao:
      execucao:
        isolamento:
          thread:
            tempo-espera-milissegundos: 1500

Na clasce principal do aplicativo, adicione anotações para ativar o Hystrix e o cliente Eureka:

package com.exemplo.microservicofornecedorhystrix1005;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.domain.EntityScan;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;

@EnableCircuitBreaker
@EntityScan("com.exemplo.*.*")
@EnableEurekaClient
@SpringBootApplication
public class AplicativoMicroservicoFornecedorHystrix1005 {
    public static void main(String[] args) {
        SpringApplication.run(AplicativoMicroservicoFornecedorHystrix1005.class, args);
    }
}

Inicie três instâncias com perfis distintos para formar o cluster.

Monitoramento com Turbine

Para monitorar o cluster, crie um projeto separado chamado microservico-consumidor-turbine-91. Adicione as dependências:

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-turbine</artifactId>
    </dependency>
</dependencies>

Configure o arquivo application.yml para Turbine:

servidor:
  porta: 91
eureka:
  cliente:
    url-servico:
      padrao: http://eureka2001.exemplo.com:2001/eureka/,http://eureka2002.exemplo.com:2002/eureka/,http://eureka2003.exemplo.com:2003/eureka/
turbine:
  app-config: microservico-aluno
  nome-cluster-expressao: "'padrao'"
spring:
  aplicacao:
    nome: turbine

Adicione @EnableTurbine à classe principal:

package com.exemplo.microservicoconsumidorturbine91;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration;
import org.springframework.cloud.netflix.turbine.EnableTurbine;

@SpringBootApplication(exclude={DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class})
@EnableTurbine
public class AplicativoMicroservicoConsumidorTurbine91 {
    public static void main(String[] args) {
        SpringApplication.run(AplicativoMicroservicoConsumidorTurbine91.class, args);
    }
}

Inicie os serviços Eureka, os fornecedores Hystrix, o consumidor e o Turbine. Acesse http://localhost:91/turbine.stream para dados em tempo real e use o dashboard Hystrix em http://localhost:90/hystrix para monitoramanto.

Integração Feign com Hystrix para Desacoplamento

Para desacoplar a lógica de fallback, evite usar @HystrixCommand diretamente no código do serviço. Em vez disso, integre com Feign. No projeto microservico-comum, adicione uma interface ClienteAlunoServico com um método hystrix():

@FeignClient(value="MICROSERVICO-ALUNO", fallbackFactory=FabricaFallbackAluno.class)
public interface ClienteAlunoServico {
    @GetMapping(value="/aluno/hystrix")
    Map<String, Object> hystrix();
}

Crie uma classe FabricaFallbackAluno implementando FallbackFactory:

package com.exemplo.microservicofornecedorhystrix.servico;

import com.exemplo.microservicocomum.ClienteAlunoServico;
import feign.hystrix.FallbackFactory;
import java.util.HashMap;
import java.util.Map;

public class FabricaFallbackAluno implements FallbackFactory<ClienteAlunoServico> {
    @Override
    public ClienteAlunoServico create(Throwable causa) {
        return new ClienteAlunoServico() {
            @Override
            public Map<String, Object> hystrix() {
                Map<String, Object> mapa = new HashMap<>();
                mapa.put("codigo", 500);
                mapa.put("info", "Sistema ocupado, tente novamente mais tarde");
                return mapa;
            }
            // Implementar outros métodos se necessário
        };
    }
}

Habilite Hystrix no Feign no arquivo application.yml do módulo comum:

feign:
  hystrix:
    enabled: true

No projeto consumidor Feign, adicione um controlador que chama o método hystrix() e anote a classe principal com @EnableFeignClients.

Ajustes de Timeout em Cluster

Em ambientes clusterizados, o timeout do Ribbon (usado pelo Feign) deve ser maior que o do Hystrix. No projeto consumidor Feign, configure:

hystrix:
  comando:
    padrao:
      execucao:
        isolamento:
          thread:
            tempo-espera-milissegundos: 1500
ribbon:
  tempo-leitura: 10000
  tempo-conexao: 9000

Isso garante que o timeout do Hystrix seja efetivo, já que o Ribbon tem um tempo padrão de 1 segundo.

Tags: Spring Cloud Hystrix Turbine Feign eureka

Publicado em 7-12 08:14