天天看點

Spring Cloud Hystrix 入門

完整源碼:https://gitee.com/wan-lianglin/springcloud-test

  1. 什麼是Hystrix

Hystrix是一個用于處理分布式系統的延遲和容錯的開源庫,在分布式系統裡,許多依賴不可避免的會調用失敗,比如逾時,異常等,Hystrix能夠保證在一個依賴出問題的情況下,不會導緻整體服務失敗,避免級聯故障,以提高分布式系統的彈性。

“斷路器”本身是一種開關裝置,當某個服務單元發生故障之後,通過斷路器的故障監控(類似熔斷保險絲),向調用方傳回一個服務預期的,可處理的備選響應(FallBack),而不是長時間的等待或者抛出調用方法無法處理的異常,這樣就可以保證了服務調用方的線程不會被長時間,不必要的占用,進而避免了故障在分布式系統中的蔓延,乃至雪崩

能幹嘛

服務降級

服務熔斷

熔斷機制是對應雪崩效應的一種微服務鍊路保護機制。

當扇對外連結路的某個微服務不可用或者響應時間太長時,會進行服務的降級,進而熔斷該節點微服務的調用,快速傳回錯誤的響應資訊。當檢測到該節點微服務調用響應正常後恢複調用鍊路。在SpringCloud架構裡熔斷機制通過Hystrix實作。Hystrix會監控微服務間調用的狀況,當失敗的調用到一定門檻值,預設是5秒内20次調用失敗就會啟動熔斷機制。熔斷機制的注解是@HystrixCommand。

服務限流

接近實時的監控

官網:Home · Netflix/Hystrix Wiki (github.com)

  1. 來簡單測試一下服務熔斷

  1. 建立一個子產品springcloud-provider-dept-hystrix-9001(直接複制springcloud-provider-dept-8001後修改一下啟動類)
Spring Cloud Hystrix 入門

2.導入依賴

<!--Hystrix-->
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-hystrix</artifactId>
    <version>1.4.6.RELEASE</version>
</dependency>
           

3.配置application.yml檔案

server:
  port: 9001

#mybatis配置
mybatis:
  type-aliases-package: com.wll.springcloud.pojo
  config-location: classpath:mybatis/mybatis-config.xml
  mapper-locations: classpath:mybatis/mapper/*.xml

#spring配置
spring:
  application:
    name: springcloud-provider-dept
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: org.gjt.mm.mysql.Driver
    url: jdbc:mysql://localhost:3306/db01?useUnicode=true&characterEncoding=utf-8
    username: root
    password: root

#Eureka配置
eureka:
  client:
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/


#info配置
info:
  app.name: wll-springcloud
  company.name: wll.com
           

4.controller層寫方法

package com.wll.springcloud.controller;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.wll.springcloud.pojo.Dept;
import com.wll.springcloud.service.DeptService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.*;

import java.util.List;

@RestController
public class DeptController {

    @Autowired
    private DeptService deptService;

    @GetMapping("/dept/get/{id}")
    @HystrixCommand(fallbackMethod = "hystrixGet")
    public Dept get(@PathVariable("id") Long id){
        Dept dept = deptService.queryById(id);
        if (dept==null){
            throw  new RuntimeException("id=>"+id+",不存在該使用者,或者資訊無法找到~");
        }
        return dept;
    }

    //備選方法
    public Dept hystrixGet(@PathVariable("id") Long id){
        return new Dept()
                .setDeptno(id)
                .setDname("id=>"+id+"沒有對應資訊,[email protected]")
                .setDb_source("no this database in MySQL");
    }
}
           

在controller層寫了get和hystrixGet兩個方法,其中hystrixGet方法為備用方法。當get方法出錯,就通過@HystrixCommand(fallbackMethod = "hystrixGet")注解來使用hystrixGet方法。

5.在啟動類中添加對熔斷的支援

package com.wll.springcloud;

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.netflix.eureka.EnableEurekaClient;

//啟動類
@SpringBootApplication
@EnableEurekaClient //在服務啟動後自動注冊到Eureka中
@EnableDiscoveryClient //使服務發現生效
@EnableCircuitBreaker //添加對熔斷的支援
public class DeptProviderHystrix_9001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProviderHystrix_9001.class);
    }
}
           

6.啟動注冊中心,啟動服務提供者(DeptProviderHystrix_9001),啟動消費者

Spring Cloud Hystrix 入門

id為1查詢成功

Spring Cloud Hystrix 入門

id為8,沒有這個id,查詢失敗,并成功調用了備用方法

補充:

7.我們修改消費者的負載均衡算法,修改為輪詢(不使用我們自定義的算法)

package com.wll.myrule;

import com.netflix.loadbalancer.IRule;
import com.netflix.loadbalancer.RandomRule;
import com.netflix.loadbalancer.RoundRobinRule;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
public class WllRule {

    @Bean
    public IRule myRule(){
        return new RoundRobinRule();  //輪詢
    }
}
           

3.服務降級

1.在springcloud-api服務中編寫DeptClientServiceFallbackFactory類:用戶端降級時傳回的具體方法,内容

package com.wll.springcloud.service;

import com.wll.springcloud.pojo.Dept;
import feign.hystrix.FallbackFactory;
import org.springframework.stereotype.Component;

import java.util.List;

//降級
@Component
public class DeptClientServiceFallbackFactory implements FallbackFactory {
    @Override
    public DeptClientService create(Throwable throwable) {
        return new DeptClientService() {
            @Override
            public Dept queryById(Long id) {
                return new Dept()
                        .setDeptno(id)
                        .setDname("id=>"+id+"沒有對應的資訊,用戶端提供了降級的資訊,這個服務現在已經被關閉")
                        .setDb_source("沒有資料~");
            }

            @Override
            public List<Dept> queryAll() {
                return null;
            }

            @Override
            public boolean addDept(Dept dept) {
                return false;
            }
        };
    }
}
           

2.在springcloud-api服務的DeptClientService類的@FeignClient注解中使用fallbackFactory

package com.wll.springcloud.service;

import com.wll.springcloud.pojo.Dept;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.GetMapping;

import java.util.List;

@Component
@FeignClient(value = "SPRINGCLOUD-PROVIDER-DEPT",fallbackFactory = DeptClientServiceFallbackFactory.class)
public interface DeptClientService {

    @GetMapping("/dept/get/{id}")
    public Dept queryById(Long id);

    @GetMapping("/dept/list")
    public List<Dept> queryAll();

    @GetMapping("/dept/add")
    public boolean addDept(Dept dept);

}
           

3.在消費者spring-consumer-dept-feign服務的配置檔案application.yml中開啟降級feign.hystrix

server:
  port: 8003

# 開啟降級feign.hystrix
feign:
  hystrix:
    enabled: true

#Eureka配置
eureka:
  client:
    register-with-eureka: false #不向Eureka注冊自己
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka,http://eureka7003.com:7003/eureka
           

4.啟動注冊中心(,springcloud-eureka-7001),開啟降級的消費者(spring-consumer-dept-feign),服務提供者(springcloud-provider-dept-8001):

Spring Cloud Hystrix 入門

可以正常通路

當我們關閉服務提供者後,再通路:

Spring Cloud Hystrix 入門

可以看到傳回了我們設定的降級消息。

總結:

按我的了解:服務降級主要是用于用戶端,服務熔斷是用于服務端。

服務熔斷:服務端 某個服務逾時或者異常。引起熔斷~,調用備用方法,讓用戶端看不見報錯資訊,相當于保險絲。

服務降級:用戶端 從整體網站請求負載考慮~,當某個服務熔斷或者關閉之後,服務将不再被調用~此時在用戶端,我們可以準備一個FallbackFactory,傳回一個預設的值(預設值)。

服務降級是我們資源緊張時,主動關閉某個伺服器,釋放資源。讓服務不再被調用,當用戶端繼續請求這個已經關閉的伺服器時,就直接在消費者傳回我們設定的内容,提示此服務已關閉。

而服務熔斷是在多個伺服器鍊路中,突然有個伺服器出錯,當機。為了不使整個服務鍊路跟着出錯,甚至于引發更多連鎖錯誤。我們使用服務熔斷,直接傳回備用方法。這些都配置在服務端,是被動防止伺服器出錯。同時還配置了負載均衡算法。

4.dashboard流監控

1.建立一個消費者子產品springcloud-consumer-hystrix-dashboard

Spring Cloud Hystrix 入門

2.導入依賴

<?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">
    <parent>
        <artifactId>springcloud</artifactId>
        <groupId>com.wll</groupId>
        <version>1.0-SNAPSHOT</version>
    </parent>
    <modelVersion>4.0.0</modelVersion>

    <artifactId>springcloud-consumer-hystrix-dashboard</artifactId>

    <!--實體類web-->
    <dependencies>
        <!--Hystrix依賴-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

        <!--hystrix-dashboard依賴-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

        <!--Ribbon-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-ribbon</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
        <!-- eureka -->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-eureka</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>

        <dependency>
            <groupId>com.wll</groupId>
            <artifactId>springcloud-api</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
        </dependency>
    </dependencies>

</project>
           

3.yml檔案

server:
  port: 9002
           

4.啟動類

package com.wll.springcloud;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

@SpringBootApplication
@EnableHystrixDashboard //開啟Dashboard
public class DeptConsumerDashboard_9002 {
    public static void main(String[] args) {
        SpringApplication.run(DeptConsumerDashboard_9002.class,args);
    }

}
           

注意,既然要監控,那麼服務端就要有監控相關的依賴,我們看看我的服務端springcloud-provider-dept-8001的依賴中是否有:

Spring Cloud Hystrix 入門

可以看到有。

5.啟動9002,通路http://localhost:9002/hystrix

Spring Cloud Hystrix 入門

成功進入監控頁面

6.監控服務提供者springcloud-provider-dept-hystrix-9001

(1)在springcloud-provider-dept-hystrix-9001pom檔案中導入Hystrix依賴

<!--Hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-hystrix</artifactId>
            <version>1.4.6.RELEASE</version>
        </dependency>
           

(2)在springcloud-provider-dept-hystrix-9001啟動類中增加一個servlet

package com.wll.springcloud;

import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.web.servlet.ServletRegistrationBean;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.context.annotation.Bean;

//啟動類
@SpringBootApplication
@EnableEurekaClient //在服務啟動後自動注冊到Eureka中
@EnableDiscoveryClient //使服務發現生效
@EnableCircuitBreaker //添加對熔斷的支援
public class DeptProviderHystrix_9001 {
    public static void main(String[] args) {
        SpringApplication.run(DeptProviderHystrix_9001.class);
    }

    //增加一個servlet
    @Bean
    public ServletRegistrationBean hystrixMetricsStreamServlet(){
        ServletRegistrationBean registrationBean = new ServletRegistrationBean(new HystrixMetricsStreamServlet());
        registrationBean.addUrlMappings("/actuator/hystrix.stream");
        return registrationBean;
    }
}
           

7.啟動注冊中心,服務提供者和dashboard監控

通路9001端口(localhost:9001/actuator/hystrix.stream):

Spring Cloud Hystrix 入門

接着監控此服務,點選按鈕Monitor Stream進行監控

Spring Cloud Hystrix 入門

調用服務提供者(9001端口)的get方法,可看到監控變化。

Spring Cloud Hystrix 入門

圖解:

一圈

實心圓:有兩種含義,他通過顔色的變化代表了執行個體的健康程度

它的健康程度從綠色<黃色<橙色<紅色遞減

該實心圓除了顔色的變化之外,它的大小也會根據執行個體的請求流量發生變化,流量越大,該實心圓就越大,是以通過該實心圓的展示,就可以在大量的執行個體中快速發現故障執行個體和高壓力執行個體。

一線

曲線:用來記錄2分鐘内流量的相對變化,可以通過它來觀察到流量的上升和下降趨勢!

Spring Cloud Hystrix 入門

所有springcloud入門相關(建議從上到下依次閱讀):

(14條消息) Spring Cloud Eureka 入門_萬1999的部落格-CSDN部落格

(6條消息) Spring Cloud Ribbon 入門_萬1999的部落格-CSDN部落格

(14條消息) Spring Cloud Hystrix 入門_萬1999的部落格-CSDN部落格

(14條消息) Zuul路由網關_萬1999的部落格-CSDN部落格

(14條消息) SpringCloud config分布式配置_萬1999的部落格-CSDN部落格