1. 程式人生 > 實用技巧 >Hystrix斷路器-1

Hystrix斷路器-1

Hystrix斷路器的概述

分散式系統面臨的問題

Hystrix是什麼

Hystrix能幹啥

1. 服務降級

2. 服務熔斷

3. 接近實時的監控

Hystrix官網資料

https://github.com/Netflix/Hystrix/wiki/How-To-Use

Hystrix官宣,停更進維

Hystrix的重要概念

服務降級(fallback),服務熔斷(break),服務限流(flowlimit)

在分散式系統中,服務與服務之間依賴錯綜複雜,一種不可避免的情況就是某些服務將會出現失敗。Hystrix是一個用於處理分散式系統的延時和容錯的開源庫,它提供了服務與服務之間的容錯功能,主要體現在延遲容錯和容錯,從而做到控制分散式系統中的聯動故障。Hystrix通過隔離服務的訪問點,阻止聯動故障,並提供故障的解決方案,從而提高了這個分散式系統的彈性。

服務降級

“斷路器”本身就是一種開關裝置。當某個服務單元發生故障後,通過斷路器的故障監控(類似熔斷保險絲),向呼叫方返回一個符合預期的,可處理的備選響應(fallBack),而不是長時間的等待或者丟擲呼叫方無法處理的異常,這樣就可以保證了服務呼叫方的執行緒不會被長時間,不必要地佔用,從而避免了故障在分散式系統中的蔓延,

乃至雪崩。

哪些情況會出現降級?

l 程式執行異常

l 超時

l 服務熔斷出發服務降級

l 執行緒池/訊號量打滿也會導致服務降級

服務熔斷

類似保險絲達到最大服務訪問後,直接拒接訪問。然後呼叫服務降級的方法並返回友好提示。

就是保險絲。

服務限流

秒殺高併發等操作,嚴禁一窩峰的過來擁擠,大家排隊,一秒鐘N個,有序進行

Hystrix案例

Hystrix支付微服務構建

構建工程

1. 新建cloud-provider-hystrix-payment8001工程

2. 新增pom
<dependencies>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-actuator</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <scope>runtime</scope> <optional>true</optional> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <dependency> <groupId>log4j</groupId> <artifactId>log4j</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>com.fengyangcai.springcloud</groupId> <artifactId>cloud-api-commons</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> </dependencies>

3. 寫yml
server:
  port: 8001
spring:
  application:
    name: cloud-provider-hystrix-payment
eureka:
  client:
    fetch-registry: true
    register-with-eureka: true
    service-url:
      defaultZone: http://localhost:7003/eureka
      #defaultZone: http://eureka7001.com:7001/eureka,http://eureka7002.com:7002/eureka #叢集版本

4. 主啟動類
@SpringBootApplication
@EnableEurekaClient
//@EnableDiscoveryClient
//@EnableCircuitBreaker//斷路器的註解
public class HystrixPaymentMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(HystrixPaymentMain8001.class,args);
    }
}

5. 業務類
Service
@Service
public class PaymentService {
//正常的訪問方法
    public String paymentInfo_OK(Integer id){
        return "執行緒池:"+Thread.currentThread().getName()+"paymentInfo_OK,id: "+id+"/t"+"哈哈";
    }
    //一般Hstrix降級放在客戶端,這裡放在服務端了只是演示而已。
    /* @HystrixCommand(fallbackMethod = "payment_TimeOutHandler",commandProperties = {
         @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
 })*/
    public String paymentInfo_TimeOut(Integer id){
            int time=1;
           // int a=10/0;
        try {
            TimeUnit.SECONDS.sleep(time);
        }catch (InterruptedException e){
            e.printStackTrace();
        }
        return "執行緒池:"+Thread.currentThread().getName()+"--paymentInfo_TimeOut,id: "+id+"/t"+"哈哈耗時:"+time+"秒";
    }

    public String payment_TimeOutHandler(Integer id){
        return  "執行緒池:"+Thread.currentThread().getName()+"--paymentInfo_TimeOut,id: "+id+"/t"+"####系統繁忙嗚嗚嗚##";
    }
}

Controller層
@RestController
@Slf4j
public class PaymentController {
    @Resource
    private PaymentService paymentService;
    @Value("${server.port}")
    private String serverPort;
    @GetMapping("/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id")Integer id){
        String result = paymentService.paymentInfo_OK(id);
        log.info("&&&&&&result"+result);
        return result;
    }
    @GetMapping("/payment/hystrix/timeout/{id}")
    public String paymentInfo_timeout(@PathVariable("id")Integer id){
        String result = paymentService.paymentInfo_TimeOut(id);
        log.info("*******result"+result);
        return result;
    }
}


6. 測試

出現情況:

Tomcat的預設的工作執行緒數被打滿了,沒有多餘的執行緒來分解壓力和處理。出現兩個都在自己轉圈圈。

上述結論

如何解決?解決的要求

建立cloud-consumer-feign-hystrix-order80消費端

Pom

<dependencies>
    <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.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-devtools</artifactId>
        <scope>runtime</scope>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
        <optional>true</optional>
    </dependency>
    <dependency>
        <groupId>com.fengyangcai.springcloud</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>1.0-SNAPSHOT</version>
    </dependency>
</dependencies>

Yml

server:
  port: 80
spring:
  application:
    name: cloud-consumer-feign-hystrix-order
eureka:
  client:
    register-with-eureka: false #表示是否將自己註冊進EurekaServer預設為true
    fetch-registry: true #是否從EurekaServer捉取已有的註冊資訊,預設為true.單節點無所謂,叢集必須設定為true才能配合ribbon使用負載均衡
    service-url:
      #defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka
      defaultZone: http://localhost:7003/eureka

主函式

其中@EnableCircuitBreaker就是引入了hystrix的熔斷註解標籤

@SpringBootApplication
@EnableFeignClients
@EnableCircuitBreaker
public class FeignHystrixOrderMain80 {
    public static void main(String[] args) {
        SpringApplication.run(FeignHystrixOrderMain80.class,args);
    }
}

使用openFeign在service層呼叫服務

@Component
@FeignClient(value = "cloud-provider-hystrix-payment")
public interface PaymentFeignHystrixService {
    @GetMapping("/consumer/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id")Integer id);

    @GetMapping("/consumer/payment/hystrix/timeout/{id}")
    public String paymentInfo_timeout(@PathVariable("id")Integer id);

}

Controller層

其中@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")是全域性的一個處理方法標籤。

@HystrixCommand是區域性的一個處理標籤。

@RestController
@Slf4j
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
public class OrderFeignHystrixController {

    @Resource
    private PaymentFeignHystrixService paymentFeignHystrixService;

    @GetMapping("/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id")Integer id){
        return paymentFeignHystrixService.paymentInfo_OK(id);
    }
    //一般Hstrix降級放在客戶端
    @GetMapping("/payment/hystrix/timeout/{id}")
   /* @HystrixCommand(fallbackMethod = "payment_TimeOutHandler",commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "1500")
    })*/
    @HystrixCommand
    public String paymentInfo_timeout(@PathVariable("id")Integer id){

        return paymentFeignHystrixService.paymentInfo_timeout(id);
    }

    public String payment_TimeOutHandler(Integer id){
        return  "我是消費方80.對方支付系統繁忙請稍後訪問";
    }
    //全域性fallback方法
    public String payment_Global_FallbackMethod(){
        return "全域性的降級處理方法";
    }
}