Spring Cloud中的斷路器Hystrix

什麼是微服務?舉個簡單的例子,我想作一個用戶管理項目,裏邊就三個功能:用戶註冊、用戶登陸、用戶詳情瀏覽。按照傳統的軟件開發方式直接建立一個Web項目,分分鐘就把這三個功能開發出來了,可是我如今想使用微服務+服務治理的方式來開發:首先我將這個項目拆分爲四個微服務,四個微服務各建一個模塊,分別是用戶註冊模塊、用戶登陸模塊、用戶詳情瀏覽模塊和數據庫操做模塊,這四個模塊經過內部服務治理互相調用。可是如今存在一個問題,這四個模塊經過服務註冊與訂閱的方式互相依賴,若是一個模塊出現故障會致使依賴它的模塊也發生故障從而發生故障蔓延,進而致使整個服務的癱瘓。好比說這裏的登陸模塊依賴於數據庫模塊,若是數據庫模塊發生故障,那麼當登陸模塊去調用數據庫模塊的時候可能得不到響應,這個調用的線程被掛起,若是處於高併發的環境下,就會致使登陸模塊也崩潰。當一個系統劃分的模塊越多,這種故障發生的頻率就會越高,對於這個問題,Spring Cloud中最重要的解決方案就是斷路器,那麼本文咱們就來看看什麼是斷路器。git


本文是Spring Cloud系列的第十篇文章,瞭解前九篇文章內容有助於更好的理解本文: github

1.使用Spring Cloud搭建服務註冊中心
2.使用Spring Cloud搭建高可用服務註冊中心
3.Spring Cloud中服務的發現與消費
4.Eureka中的核心概念
5.什麼是客戶端負載均衡
6.Spring RestTemplate中幾種常見的請求方式
7.RestTemplate的逆襲之路,從發送請求到負載均衡
8.Spring Cloud中負載均衡器概覽
9.Spring Cloud中的負載均衡策略spring


在以前的文章中咱們已經成功的搭建出服務註冊中心、服務提供者和服務消費者三個微服務,本文的案例咱們依然在這三個案例的基礎上來實現(文末提供源碼下載)。 數據庫

首先咱們分別啓動服務註冊中心,再啓動兩個服務提供者的實例,端口號分別是8080和8081,而後再啓動一個服務消費者,服務消費者的端口號爲9000,這幾個都啓動成功以後,咱們訪問http://localhost:9000/ribbon-consumer這個地址,能夠看到以下效果: 網絡

圖片描述

此時咱們關閉掉任意一個服務提供者,再去訪問這個地址,會看到以下效果: 併發

圖片描述
經過前面幾篇文章的學習,你們知道Spring Cloud中採起的默認負載均衡策略就是輪詢,因此當一個服務提供者關掉以後,刷新的時候服務請求成功和請求失敗是成對出現的:當服務消費者去請求那個被關掉的服務提供者的時候就會請求失敗,當服務消費者去請求正常的服務提供者時就能得到指望的結果。請求失敗時不能給用戶展現這樣一個ErrorPage,而應該是一個可控的頁面,OK,咱們來看看如何使用斷路器來解決這個問題。app

服務消費者中加入斷路器

首先咱們須要在服務消費者中引入hystrix,以下:負載均衡

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

修改服務消費者啓動入口類

引入hystrix以後,咱們須要在入口類上經過@EnableCircuitBreaker開啓斷路器功能,以下:微服務

@EnableCircuitBreaker
@SpringBootApplication
@EnableDiscoveryClient
public class RibbonConsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(RibbonConsumerApplication.class, args);
    }
    @LoadBalanced
    @Bean
    RestTemplate restTemplate() {
        return new RestTemplate();
    }
}

咱們也可使用一個名爲@SpringBootApplication的註解代替這三個註解,@SpringBootApplication註解的定義以下:高併發

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

實際上就是這三個註解的一個整合。

修改Controller

而後咱們建立一個HelloService類,以下:

@Service
public class HelloService {
    @Autowired
    private RestTemplate restTemplate;

    @HystrixCommand(fallbackMethod = "error")
    public String hello() {
        ResponseEntity<String> responseEntity = restTemplate.getForEntity("http://HELLO-SERVICE/hello", String.class);
        return responseEntity.getBody();
    }

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

關於這個HelloService類我說以下幾點:

1.RestTemplate執行網絡請求的操做咱們放在HelloService中來完成。
2.error方法是一個請求失敗時回調的方法。
3.在hello方法上經過@HystrixCommand註解來指定請求失敗時回調的方法。

OK,最後咱們將ConsumerController的邏輯修改爲下面這樣:

@RestController
public class ConsumerController {
    @Autowired
    private HelloService helloService;
    @RequestMapping(value = "/ribbon-consumer",method = RequestMethod.GET)
    public String helloController() {
        return helloService.hello();
    }
}

此時咱們就開啓了斷路器功能。

測試

咱們先確認服務註冊中心,兩個服務提供者的實例,端口號分別是8080和8081,一個服務消費者,端口號爲9000,一共四個實例都啓動成功,啓動成功以後,咱們再關掉一個服務提供者,此時訪問http://localhost:9000/ribbon-consumer,結果以下:
圖片描述

OK,小夥伴們看到,此時若是服務調用失敗,就會調用失敗的那個回調方法。

事實上,不單單是服務提供者被關閉時咱們須要斷路器,若是請求超時也會觸發熔斷請求,調用回調方法返回數據。

案例地址:https://github.com/lenve/SimpleSpringCloud

更多JavaEE資料請關注公衆號:

圖片描述

以上。

相關文章
相關標籤/搜索