1. 程式人生 > >5.Spring Cloud初相識-------Hystrix熔斷器

5.Spring Cloud初相識-------Hystrix熔斷器

前言:

1.介紹Hystrix

在一個分散式系統裡,許多依賴不可避免的會呼叫失敗,比如超時、異常等,如何能夠保證在一個依賴出問題的情況下,不會導致整體服務失敗,這個就是Hystrix需要做的事情。Hystrix提供了熔斷、隔離、Fallback、cache、監控等功能,能夠在一個、或多個依賴同時出現問題時保證系統依然可用。

2.為什麼使用Hystrix

在分散式系統架構中多個系統之間通常是通過遠端RPC呼叫進行通訊,也就是 A 系統呼叫 B 系統服務,B 系統呼叫 C 系統的服務。當尾部應用 C 發生故障而系統 B 沒有服務降級時候可能會導致 B,甚至系統 A 癱瘓,這種現象被稱為雪崩現象。所以在系統設計時候要使用一定的降級策略,來保證當服務提供方服務不可用時候,服務呼叫方可以切換到降級後的策略進行執行。

實戰:

1.新建服務消費者:

(1)新增依賴

<?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)修改配置

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

eureka.client.register-with-eureka=false

feign.hystrix.enabled=true

(3)開啟註解

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)配置熔斷回撥工廠

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 異常!";
            }
        };
    }

}

(5)新建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)新建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.新建服務提供者:

(1)新增依賴

<?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)修改配置

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

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

(3)開啟註解

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)新建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.測試

執行:localhost:8080/hello

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