Hystrix de SpringCloud: marco de tolerancia a fallas de clúster

En un entorno distribuido, algunos servicios dependientes pueden fallar, afectando el funcionamiento estable del sistema.
Hystrix controla la interacción de componentes entre sistemas distribuidos agregando umbrales de retardo y lógica tolerante a fallas.
Hystrix logra la tolerancia a fallas al aislar los puntos de acceso entre los servicios, detener las fallas en cascada entre ellos y brindar operaciones de respaldo.

El siguiente ejemplo es para usar en Spring Cloud.
Herramientas de desarrollo: IntelliJ IDEA 2019.2.3

Uno, lado del servidor

1. Crea un proyecto

Cree un nuevo proyecto SpringBoot en IDEA, el nombre es "spring-hystrix-server", la versión SpringBoot seleccione 2.1.10, en la selección de la interfaz Dependencias (dependencias), marque Spring Cloud Discovery ->
Eureka Server, cree el pom después de la finalización El archivo de configuración xml agrega automáticamente la última versión estable de SpringCloud como dependencia, actualmente Greenwich.SR3.
El contenido completo de pom.xml es el siguiente:

<?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>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.10.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-hystrix-server</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-hystrix-server</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR3</spring-cloud.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2. Modifique la configuración application.yml

Modifique el número de puerto a 8761; cancele el registro de su información en el servidor de Eureka y no obtenga la información de registro del servidor de Eureka.

server:
  port: 8761
eureka:
  client:
    register-with-eureka: false
    fetch-registry: false

3. Modifica el código de inicio

Agregar anotación @EnableEurekaServer

2. Proveedor de servicios

1. Crea un proyecto

Cree un nuevo proyecto SpringBoot en IDEA, excepto que el nombre es "spring-hystrix-provider", los otros pasos son los mismos que los de la creación del lado del servidor anterior.

2. Modifique la configuración application.yml

server:
  port: 8080
spring:
  application:
    name: spring-hystrix-provider
eureka:
  instance:
    hostname: localhost
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/

3. Agregue una clase de entidad User.java

package com.example.springhystrixprovider;

public class User {
    String name;
    Integer age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}

4. Modifica el código de inicio.

package com.example.springhystrixprovider;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import javax.servlet.http.HttpServletRequest;

@SpringBootApplication
@EnableEurekaClient
@RestController
public class SpringHystrixProviderApplication {

    public static void main(String[] args) {
        SpringApplication.run(SpringHystrixProviderApplication.class, args);
    }

    @RequestMapping("/hello")
    public String hello(HttpServletRequest request) {
        return "hello world." + request.getServerPort();
    }

    @RequestMapping(value="/user/{name}", produces = MediaType.APPLICATION_JSON_VALUE)
    public User user(@PathVariable String name) {
        User u = new User();
        u.setName(name);
        u.setAge(30);
        return u;
    }
}

Tres, la persona que llama al servicio

1. Crea un proyecto

Cree un nuevo proyecto SpringBoot en IDEA, el nombre es "spring-hystrix-invoker", seleccione la versión de SpringBoot 2.1.10, en la interfaz de selección de dependencias (dependencias) marque Spring Cloud Discovery -> Eureka Server, Spring Cloud Circuit Breaker -> Hystrix.
El contenido completo de pom.xml es el siguiente:

<?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>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.10.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.example</groupId>
    <artifactId>spring-hystrix-invoker</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>spring-hystrix-invoker</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <spring-cloud.version>Greenwich.SR3</spring-cloud.version>
    </properties>

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

2. Modifique la configuración application.yml

server:
port: 9000
spring:
application:
name: spring-hystrix-invoker
eureka:
instance:
hostname: localhost
client:
serviceUrl:
defaultZone: http://localhost:8761/eureka/

3. Modifica el código de inicio

Se agregaron anotaciones @EnableEurekaClient y @EnableCircuitBreaker.

package com.example.springhystrixinvoker;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker
public class SpringHystrixInvokerApplication {

    @LoadBalanced
    @Bean
    public RestTemplate getRestTemplate(){
        return new RestTemplate();
    }

    public static void main(String[] args) {
        SpringApplication.run(SpringHystrixInvokerApplication.class, args);
    }

}

4. Agregue una clase de entidad User.java

package com.example.springhystrixinvoker;

public class User {
    String name;
    Integer age;

    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public Integer getAge() {
        return age;
    }
    public void setAge(Integer age) {
        this.age = age;
    }
}

5. Agregue una clase de servicio y llame al servicio en el método de servicio.

El método de servicio está decorado con la anotación @HystrixCommand y el método de reserva está configurado.package com.example.springhystrixinvoker;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;

@Component
public class UserService {
@Autowired
private RestTemplate restTemplate;

@HystrixCommand(fallbackMethod = "getUserFallback")
public User getUser(String name){
User user = restTemplate.getForObject("http://spring-hystrix-provider/user/{name}", User.class, name);
return user;
}

public User getUserFallback(String name){
User user = new User();
user.setName("无名");
user.setAge(20);
return user;
}
}

6. Agregue el controlador InvokerController.java

package com.example.springhystrixinvoker;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.MediaType;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class InvokerController {
    @Autowired
    private UserService userService;

    @RequestMapping(value = "/invokeUser/{name}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public User invokeUser(@PathVariable String name){
        User user = userService.getUser(name);
        return user;
    }
}

Cuatro, prueba

1. Inicie el servidor.
Navegador visite http: // localhost: 8761 /, normal
2. Inicie el proveedor de servicios
Navegador visite http: // localhost: 8080 / user /
Salida de la página de Xiaoming : {"name": "小 明", "age": 30}
3 Inicie la llamada de servicio.
Navegador, visite http: // localhost: 9000 / invokeUser /
Salida de la página de Xiaoming : {"name": "Xiaoming", "age": 30}
4. Detenga el proveedor de servicios 8080 y luego visite la
salida de la página de direcciones 9000 : {" name ":" 无名 "," age ": 20}
Se puede ver que el método de reserva se activó debido a la falla de la llamada.

Cinco, anotaciones en caché

Hystrix admite el almacenamiento en caché. Si se llama a la misma interfaz en varios lugares durante una solicitud , puede considerar utilizar el almacenamiento en caché.
El almacenamiento en caché se puede realizar a través de anotaciones. Las funciones de solicitud de combinación y almacenamiento en caché deben inicializarse antes de que se pueda realizar el contexto de la solicitud.

1. Cree un nuevo javax.servlet.Filter para crear y destruir el contexto de solicitud de Hystrix

package com.example.springhystrixinvoker;

import com.netflix.hystrix.strategy.concurrency.HystrixRequestContext;

import javax.servlet.*;
import javax.servlet.annotation.WebFilter;
import java.io.IOException;

@WebFilter(urlPatterns = "/*", filterName = "hystrixFilter")
public class HystrixFilter implements Filter {
    public void init(FilterConfig filterConfig) throws ServletException {
    }

    public void doFilter(ServletRequest request, ServletResponse response,
                         FilterChain chain) throws IOException, ServletException {
        HystrixRequestContext context = HystrixRequestContext.initializeContext();
        try{
            chain.doFilter(request,response);
        }finally {
            context.shutdown();
        }
    }

    public void destroy() {
    }
}

2. Agregue la anotación @ServletComponentScan a la clase de inicio

3. Escriba métodos de servicio y use anotaciones en caché

(1) @CacheResult El método modificado devuelve el resultado se almacenará en caché y la colocación de @HystrixCommand
(2) @CacheRemove invalida la caché
(3) @CacheKey modifica el parámetro del método, lo que significa que el parámetro se usa como clave de caché

package com.example.springhystrixinvoker;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheRemove;
import com.netflix.hystrix.contrib.javanica.cache.annotation.CacheResult;
import org.springframework.stereotype.Component;

@Component
public class CacheService {
    @CacheResult
    @HystrixCommand(commandKey = "removeKey")
    public String cacheMethod(String name){
        System.out.println("执行cacheMethod方法");
        return "hello";
    }

    @CacheRemove(commandKey = "removeKey")
    @HystrixCommand(commandKey = "removeKey")
    public String updateMethod(String name){
        System.out.println("执行updateMethod方法");
        return "update";
    }
}

4. Llame al controlador

Acceso al navegador: http: // localhost: 9000 / cacheMethod, salida de la consola IDEA:控制器调用服务:0
执行cacheMethod方法
控制器调用服务:1
控制器调用服务:2
控制器调用服务:3
控制器调用服务:4
控制器调用服务:5
执行updateMethod方法
控制器调用服务:6
执行cacheMethod方法
控制器调用服务:7
控制器调用服务:8
控制器调用服务:9

6. Integración de Feign e Hystrix

Modificar el código del proyecto de la persona que llama al servicio
1. Agregar dependencia de Fingir a pom.xml

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

2. Modifique la configuración application.yml

Agregue la siguiente configuración: Configuración de Hystrix de Open Feign

feign:
  hystrix:
    enabled: true

3. Agregue la anotación @EnableFeignClients a la clase de inicio

4. Nueva interfaz de Fingirpackage com.example.springhystrixinvoker;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

//指定调用的服务名称
@FeignClient(name="spring-hystrix-provider", fallback = UserClient.UserClientFallback.class)
public interface UserClient {
@RequestMapping(method = RequestMethod.GET, value = "/user/{name}")
User getUser(@PathVariable("name") String name);

@Component
static class UserClientFallback implements UserClient{
public User getUser(String name){
User user = new User();
user.setName("无名");
user.setAge(20);
return user;
}
}
}

5. Controlador InvokerController, agregar código

    @Autowired
    private UserClient userClient;

    @RequestMapping(value = "/invokeUser2/{name}", method = RequestMethod.GET, produces = MediaType.APPLICATION_JSON_VALUE)
    public User invokeUser2(@PathVariable String name){
        User user = userClient.getUser(name);
        return user;
    }

 

Supongo que te gusta

Origin blog.csdn.net/gdjlc/article/details/115007862
Recomendado
Clasificación