5.Spring Cloud's First Acquaintance--Hystrix Fuse

Keywords: Java Spring Maven Apache

Preface:

1. Introduction to Hystrix

In a distributed system, many dependencies inevitably fail to invoke, such as timeouts, exceptions, and so on. How to ensure that the whole service fails when a dependency fails is what Hystrix needs to do. Hystrix provides functions such as fuse, isolation, Fallback, cache, monitoring and so on. It can ensure that the system is still available when one or more dependencies have problems at the same time.

2. Why use Hystrix

In distributed system architecture, communication between multiple systems is usually carried out through remote RPC calls, that is, system A calls system B services, and system B calls system C services. When tail application C fails and system B fails to downgrade, it may cause B, or even system A to be paralyzed. This phenomenon is called avalanche phenomenon. Therefore, in the design of the system, we should use a certain downgrading strategy to ensure that when the service provider service is not available, the service caller can switch to the downgraded policy for execution.

Actual combat:

1. New service consumers:

(1) Adding dependencies

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xm.cloud</groupId>
    <artifactId>cl_hello_consumer_hy</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>cl_hello_consumer_hy</name>
    <description>This is a Web about springcloud</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR2</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </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) Modify configuration

eureka.client.service-url.defaultZone=http://127.0.0.1:7001/eureka/

eureka.client.register-with-eureka=false

feign.hystrix.enabled=true

(3) Opening Notes

package com.xm.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.openfeign.EnableFeignClients;

@EnableDiscoveryClient
@EnableFeignClients
@SpringBootApplication
public class ClHelloConsumerHyApplication {

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

(4) Configuration of Fuse Callback Plant

package com.xm.cloud.fallback;

import org.springframework.stereotype.Component;

import com.xm.cloud.service.HelloService;

import feign.hystrix.FallbackFactory;

@Component
public class HelloServiceFallbackFactory implements FallbackFactory<HelloService> {

    @Override
    public HelloService create(Throwable cause) {
        return new HelloService() {
            
            @Override
            public String sayHello() {
                return "HelloService Abnormal!";
            }
        };
    }

}

(5) New Service

package com.xm.cloud.service;

import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;

import com.xm.cloud.fallback.HelloServiceFallbackFactory;

@FeignClient(value="CL-HELLO-PRODUCER",fallbackFactory=HelloServiceFallbackFactory.class)
public interface HelloService {
    
    @GetMapping("/hello")
    public String sayHello();

}

(6) New Controller

package com.xm.cloud.controller;

import java.util.ArrayList;
import java.util.List;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.xm.cloud.service.HelloService;

@RestController
public class HelloController {
    
    @Autowired
    private HelloService helloService;
    
    @GetMapping("/hello")
    public List<String> sayHello() {
        List<String> list = new ArrayList<String>();
        for(int i=0;i<10;i++) {
            list.add(helloService.sayHello());
        }
        return list;
    }

}

2. New service providers:

(1) Adding dependencies

<?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 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.xm.cloud</groupId>
    <artifactId>cl_hello_producer_hy</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>cl_hello_producer_hy</name>
    <description>This is a Web about springcloud</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.0.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Finchley.SR2</spring-cloud.version>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</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) Modify configuration

server.port=8001
spring.application.name=cl-hello-producer

eureka.client.service-url.defaultZone=http://127.0.0.1:7001/eureka/

(3) Opening Notes

package com.xm.cloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

@EnableDiscoveryClient
@EnableCircuitBreaker
@SpringBootApplication
public class ClHelloProducerHyApplication {

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

(4) New Controller

package com.xm.cloud.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

@RestController
public class HelloController {
    
    @GetMapping("/hello")
    @HystrixCommand
    public String sayHello() {
        
        if(Math.random()>0.5) {
            throw new RuntimeException();
        } else {
            return "Hello spring cloud!";
        }
    }

}

3. test

Run: localhost:8080/hello

0 "HelloService exception! "
1 "Hello spring cloud!"
2 "HelloService exception! "
3 "Hello spring cloud!"
4 "Hello spring cloud!"
5 "Hello spring cloud!"
6 "Hello spring cloud!"
7 "Hello spring cloud!"
8 "HelloService exception! "
9 "Hello spring cloud!"

Posted by mrdonrule on Thu, 24 Jan 2019 14:48:13 -0800