Spring Cloud學習系列第三章:雲計算斷路器模式實現庫Hystrix

一、簡介

  微服務之間的調用模式是在不同進程間通過網絡遠程調用,內存間調用和遠程調用之間的巨大差異之一是遠程調用可能會失敗,或者在沒有響應的情況下掛起,直到達到超時限制。如果在無響應的服務提供者上有很多呼叫者,那麼就可能會用盡關鍵資源,如內存、CPU、網絡連接等,從而導致跨多個系統的級聯故障。爲解決這種問題,大神們提出了斷路器模式。

  斷路器背後的基本思路很簡單。您將一個受保護的函數調用包裝在斷路器對象中,該對象監視故障。一旦故障達到一定閾值,斷路器跳閘,並且斷路器的所有進一步調用都將返回錯誤,而完全不進行保護呼叫。通常,如果斷路器跳閘,您還需要某種監視器警報。Hystrix就是Netflix 爲實現斷路器模式而開發的一個庫,方便開發者整合進自己的雲計算服務中。

二、Feign搭配Hystrix

  繼續我們上一章所講,使用Feign客戶端搭配Hystrix。由於Feign中是自帶Hystrix庫的,所以我們不需要修改POM,代碼只需要再FeignClient那裏加上fallback,也就是回退:當電路斷開或出現錯誤時執行的默認代碼路徑。不過首先呢,我們先實現回退的處理邏輯,代碼如下。

package com.nan.feigndemo.client;

import org.springframework.stereotype.Component;

@Component
public class HelloServiceClientFallback implements HelloServiceClient {

    @Override
    public String hello(String name) {
        return "Error: Hello service error";
    }

}

  代碼簡單實現一下我們的client接口。然後在FeignClient註解增加fallback屬性,如下。

package com.nan.feigndemo.client;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;

@FeignClient(value = "HelloService", fallback = HelloServiceClientFallback.class)
public interface HelloServiceClient {

    @RequestMapping("/hello")
    String hello(@RequestParam("name") String name);

}

  然後是配置文件,有一個重要屬性,feign.hystrix.enabled,這個值默認是true的,也就是說feign默認是開啓hystrix功能的,但是有的情況下我們用feign並不需要斷路器,例如訪問量較小的服務,這個屬性就需要改成false,爲了配合本教程,我還是顯示在配置文件中聲明一下,內容如下。

server:
  port: 8080
spring:
  application:
    name: FeignDemo
eureka:
  client:
    serviceUrl:
      defaultZone: http://node01:8081/eureka/,http://node02:8082/eureka/
feign:
  hystrix:
    enabled: true

  代碼部分完了,接下來就是驗證了。首先我們只啓動Eureka server和feigndemo項目,service-hello項目不要啓動,然後在瀏覽器輸入http://localhost:8080/feigndemo?name=秦始皇,可以看到瀏覽器回顯 Error: Hello service error;然後啓動service-hello項目,在輸入接口訪問地址,瀏覽器回顯  Hello 秦始皇, this client port is 9091,斷路器發揮作用了。

三、Hystrix Dashboard

  斷路器確實是個好東西,但是我們怎麼能清楚當前斷路器的狀況呢?還好,Spring cloud提供了一個可視化web頁面,就是Hystrix Dashboard,它以有效的方式顯示每個斷路器的運行狀況。我們繼續改進feigndemo項目,首先要加入Hystrix指標流包,就是增加依賴spring-boot-starter-actuator,這將使/hystrix.stream作爲管理端點。然後再加入Hystrix Dashboard啓動器的依賴spring-cloud-starter-hystrix-dashboard,修改後的pom如下。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.nan</groupId>
    <artifactId>feigndemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>feigndemo</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR2</spring-cloud.version>
    </properties>

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

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

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

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

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>
</project>

  然後市項目啓動入口文件,如下。

package com.nan.feigndemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

@SpringBootApplication
@EnableEurekaClient
@EnableFeignClients
@EnableHystrixDashboard
@EnableHystrix
public class FeigndemoApplication {

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

}

  然後在瀏覽器輸入http://localhost:8080/hystrix,就會看到如下畫面。


  最上面的長輸入框輸入http://localhost:8080/hystrix.stream,Title輸入test,然後就會看到如下畫面。


四、聚合監控Turbine

  Hystrix Dashboard確實不錯,但也有缺點,就是隻監控一個應用,而云計算是需要多個應用協同工作的,所以Netflix又提供了一個聚合監控的工具Turbine,作用就是將多個服務的狀況集合到一個stream裏面,然後在dashboard看到所有服務,爲了方便此次驗證,我們新增一個user service,基本結構和hello service一樣,這裏就不重複貼代碼了,源碼請參考我的githu,https://github.com/ArnoWang1/springcloud_study,謝謝。
  另外我們還要創建一個Turbine的項目,這個項目基本不用寫代碼,配置配置就好,項目pom如下。

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>com.nan</groupId>
    <artifactId>turbinedemo</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <packaging>jar</packaging>

    <name>turbinedemo</name>
    <description>Demo project for Spring Boot</description>

    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>1.5.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>

    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
        <java.version>1.8</java.version>
        <spring-cloud.version>Dalston.SR2</spring-cloud.version>
    </properties>

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

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

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <dependencyManagement>
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-dependencies</artifactId>
                <version>${spring-cloud.version}</version>
                <type>pom</type>
                <scope>import</scope>
            </dependency>
        </dependencies>
    </dependencyManagement>

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

    <repositories>
        <repository>
            <id>aliyunmaven</id>
            <url>http://maven.aliyun.com/nexus/content/groups/public/</url>
        </repository>
    </repositories>
</project>

  項目啓動入口增加EnableTurbine註解。

package com.nan.turbinedemo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.turbine.EnableTurbine;

@SpringBootApplication
@EnableTurbine
public class TurbinedemoApplication {

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

  比較重要的是配置文件了,如下。

spring:
  application:
    name: turbine
server:
  port: 7070
turbine:
  app-config: FeignDemo
  clusterNameExpression: new String("default")
  aggregator:
    clusterConfig: default
eureka:
  client:
    service-url:
      defaultZone: http://node01:8081/eureka/,http://node02:8082/eureka/

  新出現的就是turbine的配置了,其中app-config指eureka中使用了hystrix的服務,因爲我們的feigndemo使用了2個其他服務,所以這裏只需要配feigndemo項目,clusterNameExpression指的是集羣名稱,功能是可以自定義集羣名稱, 默認是appName,此時clusterConfig也需要配置成應用名稱;當clusterNameExpression爲default時,clusterConfig也是default;當clusterNameExpression配置metadata['cluster']元數據時,被監控應用則配置了類似eureka.instance.metadata-map.cluster: ABC,clusterConfig需要配置成ABC。
  OK,然後啓動turbine項目,在hystrix dashboard界面的stream輸入框中填入http://localhost:7070/turbine.stream,就可以在瀏覽器看到這裏顯示了我們的2個服務。


  以上就是筆者目前所學,還是很初級的內容,如果有什麼錯誤和遺漏,還請見諒並指正,不勝感激


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章