1. 程式人生 > 實用技巧 >Spring Cloud:Hystrix服務降級

Spring Cloud:Hystrix服務降級

背景

在一個複雜的分散式體系中,可能有數十個依賴關係,這些依賴關係在某些時候將不可避免地失敗。
服務雪崩:
多個微服務之間呼叫的時候,服務A呼叫B,B又呼叫C,C又呼叫其他微服務...,在這個鏈路上某個微服務呼叫響應時間過長或者不可用,對A地呼叫會佔用越來越多的系統資源,進而引起系統崩潰,所謂地“服務雪崩”。
Hystrix是一個用於處理分散式系統地延遲容錯的開源庫,在分散式系統裡,許多依賴不可避免地會呼叫失敗(超時、異常)等,Hystrix能夠保證在一個依賴出問題的情況下,不會導致整體服務失敗,避免機連故障,以提高分散式系統的彈性。
"斷路器"本身是一種開關,當某個服務單元發生故障後,通過斷路器的故障監控,向呼叫方返回一個符合預期、可處理的備選響應(FallBack),而不是長時間的等待或者丟擲呼叫方法無法處理的異常

,這樣就保證了服務呼叫方的執行緒不會被長時間、不必要的佔用,從而避免故障在分散式系統中的蔓延,乃至雪崩。

Hystrix重要概念

服務降級fallback

伺服器繁忙,請稍後嘗試,不讓客戶端等待並立即返回一個友好提示,fallback
服務降級情況:

  • 程式執行異常
  • 超時
  • 程式熔斷觸發服務降級
  • 執行緒池/訊號量打滿也會導致服務降級

服務熔斷break

類比保險絲達到最大服務訪問後,直接拒絕訪問,拉閘限電,然後呼叫服務降級的方法並返回友好提示。
服務降級->熔斷->恢復呼叫鏈路。

服務限流flowlimit

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

服務端降級初體驗

部分依賴:

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

Service方法

@Service
public class PaymentService {

    /**
     * @Author wen.jie
     * @Description fallbackMethod中定義了回撥方法
     *              HystrixProperty中定義了超時時間
     * @Date 2020/9/6 13:00
     **/
    @HystrixCommand(fallbackMethod = "paymentInfo_Handler",commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
    })
    public String paymentInfoTimeOut(Integer id){
        int time = 5;
        try {
            TimeUnit.SECONDS.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "執行緒池:"+Thread.currentThread().getName()+"  paymentInfoTimeOut"+":"+id;
    }

    /**
     * @Author wen.jie
     * @Description 服務降級的fallback方法
     * @Date 2020/9/6 12:58
     **/
    public String paymentInfo_Handler(Integer id){
        return "執行緒池:"+Thread.currentThread().getName()+"  paymentInfoTimeOut"+":"+id+"=====hystrix-handler";
    }

}

主啟動類上加上@EnableCircuitBreaker註解或者在主啟動類上直接加上@SpringCloudApplication

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

啟動服務後,呼叫此方法,發現三秒後呼叫了FallBack方法。

全域性服務降級

在當前類上標註@DefaultProperties(defaultFallback = "paymentIfo_Global_Handler"),表明當前類的FallBack方法,都去找paymentIfo_Global_Handler方法,然後在需要服務降級的方法上只加上@HystrixConmmand就行了

@RestController
@DefaultProperties(defaultFallback = "paymentIfo_Global_Handler")
public class OrderHystrixController {
    @Autowired
    private PaymentHystrixService paymentHystrixService;

    @HystrixCommand
    @GetMapping("/consumer/payment/hystrix/timeout/{id}")
    public String paymentInfoTimeout(@PathVariable Integer id)
    {
        return paymentHystrixService.paymentInfoTimeout(id);
    }

    public String paymentIfo_Global_Handler(){
        return "執行緒池:"+Thread.currentThread().getName()+"=====hystrix-handler-order-global";
    }
}

執行效果:

但是FallBack混在controller中,有點混亂,且耦合度高。
我們只需要為Feign客戶端定義的介面新增一個服務降級處理的實現類即可實現解耦。
Feign介面:

@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = PaymentFallBackService.class)
public interface PaymentHystrixService {
    @GetMapping("/payment/hystrix/timeout/{id}")
    public String paymentInfoTimeout(@PathVariable("id") Integer id);
}

服務降級處理的實現類:

@Component
public class PaymentFallBackService implements PaymentHystrixService {
    @Override
    public String paymentInfoTimeout(Integer id) {
        return "PaymentFallBackService--fallback";
    }
}

配置yml

feign:
  hystrix:
    #在feign中開啟hystrix
    enabled: true

hystrix:
  command:
    default:  #default全域性有效,service id指定應用有效
      execution:
        timeout:
          #如果enabled設定為false,則請求超時交給ribbon控制,為true,則超時作為熔斷根據
          enabled: true
        isolation:
          thread:
            timeoutInMilliseconds: 3000 #斷路器超時時間,預設1000ms