(五)springcloud 斷路器-Spring Cloud Netflix Hystrix


較低級別的服務中的服務故障可能導致級聯故障一直到用戶。 當對特定服務的調用超過circuitBreaker.requestVolumeThreshold(默認值:20個請求)且失敗百分比大於circuit.rolllingStats.timeInMilliseconds定義的滾動窗口中的circuitBreaker.errorThresholdPercentage(默認值:> 50%)時(默認值:10秒)

設計原則:

  1. 防止單個服務的故障,耗盡整個系統服務的容器(比如tomcat)的線程資源,避免分布式環境里大量級聯失敗。通過第三方客戶端訪問(通常是通過網絡)依賴服務出現失敗、拒絕、超時或短路時執行回退邏輯
  2. 用快速失敗代替排隊(每個依賴服務維護一個小的線程池或信號量,當線程池滿或信號量滿,會立即拒絕服務而不會排隊等待)和優雅的服務降級;當依賴服務失效后又恢復正常,快速恢復
  3. 提供接近實時的監控和警報,從而能夠快速發現故障和修復。監控信息包括請求成功,失敗(客戶端拋出的異常),超時和線程拒絕。如果訪問依賴服務的錯誤百分比超過閾值,斷路器會跳閘,此時服務會在一段時間內停止對特定服務的所有請求
  4. 將所有請求外部系統(或請求依賴服務)封裝到HystrixCommand或HystrixObservableCommand對象中,然后這些請求在一個獨立的線程中執行。使用隔離技術來限制任何一個依賴的失敗對系統的影響。每個依賴服務維護一個小的線程池(或信號量),當線程池滿或信號量滿,會立即拒絕服務而不會排隊等待

功能特性:

  1. 請求熔斷: 當Hystrix Command請求后端服務失敗數量超過一定比例(默認50%), 斷路器會切換到開路狀態(Open). 這時所有請求會直接失敗而不會發送到后端服務. 斷路器保持在開路狀態一段時間后(默認5秒), 自動切換到半開路狀態(HALF-OPEN)。這時會判斷下一次請求的返回情況, 如果請求成功, 斷路器切回閉路狀態(CLOSED), 否則重新切換到開路狀態(OPEN). Hystrix的斷路器就像我們家庭電路中的保險絲, 一旦后端服務不可用, 斷路器會直接切斷請求鏈, 避免發送大量無效請求影響系統吞吐量, 並且斷路器有自我檢測並恢復的能力.
  2. 服務降級:Fallback相當於是降級操作. 對於查詢操作, 可以實現一個fallback方法, 當請求后端服務出現異常的時候, 可以使用fallback方法返回的值. fallback方法的返回值一般是設置的默認值或者來自緩存
  3. 依賴隔離(采用艙壁模式,Docker就是艙壁模式的一種):在Hystrix中, 主要通過線程池來實現資源隔離. 通常在使用的時候我們會根據調用的遠程服務划分出多個線程池
  4. 請求緩存
  5. 請求合並

Ribbon集成斷路器

1、基於之前的服務,引入Hystrix依賴

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

2、開啟斷路器功能

@EnableCircuitBreaker:加載斷路器配置

@EnableCircuitBreaker

也可以使用@SpringCloudApplication注解:三合一

@Target({ElementType.TYPE})
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Inherited
@SpringBootApplication
@EnableDiscoveryClient
@EnableCircuitBreaker
public @interface SpringCloudApplication {
}

3、創建fallback方法,指定為某個接口的降級

@SpringCloudApplication
public class ConsumerRibbonApplication {

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

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

    @RestController
    @RequestMapping("/api/v1/consumer")
    class ProviderController {

        private static final String SERVICE_NAME = "provider-server";
        private static final String GET_PORT = "/api/v1/provider/port";

        @Resource
        private RestTemplate restTemplate;

        @GetMapping
        @HystrixCommand(fallbackMethod = "consumerFallback")
        public String consumer() {
            ResponseEntity<String> forEntity = restTemplate.getForEntity("http://" + SERVICE_NAME + GET_PORT, String.class, (Object) null);
            return forEntity.getBody();
        }

        public String consumerFallback() {
            return "provider error";
        }

    }

}

hystrix:配置

hystrix:
  command:
    default:
      execution:
        isolation:
          strategy: SEMAPHORE
          thread:
            timeoutInMilliseconds: 60000
  shareSecurityContext: true

驗證:

訪問消費者:http://localhost:3000/api/v1/consumer

獲得響應:2000

Feign集成斷路器

引入依賴和開啟配置和Ribbon一樣

1、在@FeignClient上聲明

@FeignClient(name = "provider-server", fallback = ProviderClientFallback.class)
@RequestMapping("/api/v1/provider")
public interface ProviderClient {

    @GetMapping("/port")
    String port();

}

2、開啟配置feign.hystrix.enabled=true

server:
  port: 3001
spring:
  application:
    name: consumer-server-feign
  profiles:
    active: dev
  cloud:
    config:
      label: master
      profile: ${spring.profiles.active}
      discovery:
        service-id: config-server
        enabled: true

feign:
  hystrix:
    enabled: true

eureka:
  client:
    service-url:
      defaultZone: http://127.0.0.1:8761/eureka/

3、編寫fallback類

public class ProviderClientFallback implements ProviderClient {

    @Override
    public String port() {
        return "provider error";
    }

}

4、在聲明類@FeignClient上指定fallback屬性

@FeignClient(name = "provider-server", fallback = ProviderClientFallback.class)
@RequestMapping("/api/v1/provider")
public interface ProviderClient {

    @GetMapping("/port")
    String port();

}

驗證:

訪問消費者:http://localhost:3000/api/v1/consumer

獲得響應:2000

關閉生產者服務:http://localhost:3000/api/v1/consumer

獲得響應:provider error

5、換成指定FallbackFactory,可以獲取到異常對象

@FeignClient(name = "provider-server",
        fallbackFactory = HystrixClient.HystrixClientFallback.class,
        path = "/api/v1/provider")
public interface HystrixClient {

    @GetMapping("/port")
    String port();

    @Component
    class HystrixClientFallback implements FallbackFactory<HystrixClient> {

        @Override
        public HystrixClient create(Throwable throwable) {
            return new HystrixClient() {
                @Override
                public String port() {
                    return "provider error: " + throwable;
                }
            };
        }
    }
}

驗證:

訪問消費者:http://localhost:3000/api/v1/consumer

獲得響應:2000

關閉生產者服務:http://localhost:3000/api/v1/consumer

獲得響應:provider error: java.lang.RuntimeException: com.netflix.client.ClientException: Load balancer does not have available server for client: provider-server

Hystrix Metrics Stream

包含依賴關系spring-boot-starter-actuator,設置 management.endpoints.web.exposure.include: hystrix.stream。這樣做會將/actuator/hystrix.stream管理端點公開

依賴:

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

配置:

# 全部開放監控端點
management:
  endpoints:
    web:
      exposure:
        include: "*"

驗證:

GET /actuator/metrics
GET /actuator/metrics/{requiredMetricName}
{[/actuator/metrics/{requiredMetricName}],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 
{[/actuator/metrics],methods=[GET],produces=[application/vnd.spring-boot.actuator.v2+json || application/json]}" 

斷路器:Hystrix儀表板

1、添加依賴項:spring-cloud-starter-netflix-hystrix-dashboard

<dependency>
  <groupId>org.springframework.cloud</groupId>
  <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>

2、使用@EnableHystrixDashboard注解開啟儀表盤

@EnableFeignClients
@SpringCloudApplication
@EnableHystrixDashboard
public class ConsumerFeignApplication {
}

3、訪問/hystrix並將儀表板指向/hystrix.streamHystrix客戶端應用程序中的單個實例的端點。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM