Hystrix-線程隔離,服務降級

一、線程隔離示意圖:

在這裏插入圖片描述
解讀:

Hystrix爲每個依賴服務調用分配一個小的線程池,如果線程池已滿調用將被立即拒絕,默認不採用排隊.加速失敗判定時間。

用戶的請求將不再直接訪問服務,而是通過線程池中的空閒線程來訪問服務,如果線程池已滿,或者請求超時,則會進行降級處理,什麼是服務降級?

服務降級:優先保證核心服務,而非核心服務不可用或弱可用

用戶的請求故障時,不會被阻塞,更不會無休止的等待或者看到系統崩潰,至少可以看到一個執行結果(例如返回友好的提示信息) 。

服務降級雖然會導致請求失敗,但是不會導致阻塞,而且最多會影響這個依賴服務對應的線程池中的資源,對其它服務沒有響應。

觸發Hystix服務降級的情況:

  • 線程池已滿
  • 請求超時

二、實踐代碼

1、首先在itcast-service-consumer的pom.xml中引入Hystrix依賴:

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

2、開啓熔斷

在這裏插入圖片描述
可以看到,我們類上的註解越來越多,在微服務中,經常會引入上面的三個註解,於是Spring就提供了一個組合註解:@SpringCloudApplication
在這裏插入圖片描述
因此,我們可以使用這個組合註解來代替之前的3個註解。

@SpringCloudApplication
public class ItcastServiceConsumerApplication {

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

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

3、編寫降級邏輯

我們改造itcast-service-consumer,當目標服務的調用出現故障,我們希望快速失敗,給用戶一個友好提示。因此需要提前編寫好失敗時的降級處理邏輯,要使用HystixCommond來完成:

@Controller
@RequestMapping("consumer/user")
public class UserController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping
    @ResponseBody
    @HystrixCommand(fallbackMethod = "queryUserByIdFallBack")
    public String queryUserById(@RequestParam("id") Long id) {
        String user = this.restTemplate.getForObject("http://service-provider/user/" + id, String.class);
        return user;
    }

    public String queryUserByIdFallBack(Long id){
        return "請求繁忙,請稍後再試!";
    }
}

要注意,因爲熔斷的降級邏輯方法必須跟正常邏輯方法保證:相同的參數列表和返回值聲明。失敗邏輯中返回User對象沒有太大意義,一般會返回友好提示。所以我們把queryById的方法改造爲返回String,反正也是Json數據。這樣失敗邏輯中返回一個錯誤說明,會比較方便。

說明:

  • @HystrixCommand(fallbackMethod = “queryByIdFallBack”):用來聲明一個降級邏輯的方法

測試:

當itcast-service-provder正常提供服務時,訪問與以前一致。但是當我們將itcast-service-provider停機時,會發現頁面返回了降級處理信息:
在這裏插入圖片描述

4、默認FallBack

我們剛纔把fallback寫在了某個業務方法上,如果這樣的方法很多,那豈不是要寫很多。所以我們可以把Fallback配置加在類上,實現默認fallback:

@Controller
@RequestMapping("consumer/user")
@DefaultProperties(defaultFallback = "fallBackMethod") // 指定一個類的全局熔斷方法
public class UserController {

    @Autowired
    private RestTemplate restTemplate;

    @GetMapping
    @ResponseBody
    @HystrixCommand // 標記該方法需要熔斷
    public String queryUserById(@RequestParam("id") Long id) {
        String user = this.restTemplate.getForObject("http://service-provider/user/" + id, String.class);
        return user;
    }

    /**
     * 熔斷方法
     * 返回值要和被熔斷的方法的返回值一致
     * 熔斷方法不需要參數
     * @return
     */
    public String fallBackMethod(){
        return "請求繁忙,請稍後再試!";
    }
}
  • @DefaultProperties(defaultFallback = “defaultFallBack”):在類上指明統一的失敗降級方法
  • @HystrixCommand:在方法上直接使用該註解,使用默認的剪輯方法。
  • defaultFallback:默認降級方法,不用任何參數,以匹配更多方法,但是返回值一定一致
    在這裏插入圖片描述

5、設置超時

在之前的案例中,請求在超過1秒後都會返回錯誤信息,這是因爲Hystix的默認超時時長爲1,我們可以通過配置修改這個值:

我們可以通過hystrix.command.default.execution.isolation.thread.timeoutInMilliseconds來設置Hystrix超時時間。該配置沒有提示。

hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 6000 # 設置hystrix的超時時間爲6000ms

改造服務提供者

改造服務提供者的UserController接口,隨機休眠一段時間,以觸發熔斷:

@GetMapping("{id}")
public User queryUserById(@PathVariable("id") Long id) {
    try {
        Thread.sleep(6000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return this.userService.queryUserById(id);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章