Hystrix基礎以及如果配合Feign使用Hystrix

Hystrix

1.Hystrix 是什麼?

在分佈式的環境下,在訪問一些服務的時候不可避免的會有失敗的情況.比如其中一些服務器宕機了導致該服務器的的服務無法訪問.Hystrix就是一個幫助在服務與服務之間交互的時候添加延遲和容錯邏輯的一個組件.

2.Hystrix 用來做什麼?

  1. 爲使用第三方工具訪問依賴服務(通常是通過網絡的訪問)提供失敗和延遲保護
  2. 阻止在複雜的分佈是環境中由於某個或者幾個服務不可用而導致整個服務癱瘓(服務雪崩)
  3. 快速失敗與快速恢復
  4. 提供接近真實時間的監控和報警

3.怎麼使用Hystrix,以及Hystrix的配置屬性詳情

  1. 怎麼使用原生Hystrix
  2. Hystrix的配置屬性詳情

4.使用Feign集成Hystrix

Feign集成Hystrix在SpringCloud項目可以很簡單的實現,我們唯一需要注意的是在Feign中使用Hystrix, groupKey,commandKey,ThreadPoolKey 分別爲serviceId(Eureka服務註冊Id),類名#方法名(方法參數類型),serviceId.意味着他們同一個FeignClient下公用同一個ThreadPool但是有獨立的熔斷器,和其他配置信息.下面附上一些代碼:

使用的cloud的版本爲Edgware.SR5

<parent>
		<groupId>org.springframework.cloud</groupId>
		<artifactId>spring-cloud-starter-parent</artifactId>
		<version>Edgware.SR5</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>
	</properties>

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

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

		<!--Ribbon-->
		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-starter-ribbon</artifactId>
		</dependency>

		<!-- hystrix斷路器組件依賴 -->
		<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-actuator</artifactId>
		</dependency>

		<!--測試-->
		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>

	</dependencies>


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

	<repositories>
		<repository>
			<id>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>

啓動類

package com.example.hystrix;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

@SpringBootApplication
@EnableCircuitBreaker
@EnableDiscoveryClient
@EnableFeignClients
@EnableHystrixDashboard
public class DemoApplication {

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

FeignClient 類

package com.example.hystrix;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;


@FeignClient(name = "USERMANAGEMENT-SERVICE", fallback = UserClientFallback.class)
public interface UserClient {

    @HystrixCommand(fallbackMethod = "findUserByUsername")
    @RequestMapping(value = "/users/{username}", method = RequestMethod.GET)
    public User findUserByUsername(@PathVariable("username") String username);

    @HystrixCommand(ignoreExceptions = {RuntimeException.class})
    @RequestMapping(value = "/users/id/{id}", method = RequestMethod.GET)
    public User findUserById(@PathVariable("id") Integer id);


}

Fallback 類

package com.example.hystrix;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;


@Component
public class UserClientFallback implements UserClient {

    private static final Logger LOGGER = LoggerFactory.getLogger(UserClientFallback.class);

    @Override
    public User findUserByUsername(String username) {
        System.out.println("enter fallback method...");
        return new User(username, 1);
    }

    @Override
    public User findUserById(Integer id) {
        System.out.println("enter fallback method...");
        return new User("normal", 1);
    }

}

配置文件

server:
  port: 8089

spring:
  application:
    name: learn-hystrix

eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
    registerWithEureka: true
  instance:
    preferIpAddress: true
    instance-id: ${spring.cloud.client.ipAddress}:${server.port}


feign:
  hystrix:
    enabled: true

hystrix:
  command:
    "UserClient#findUserByUsername(String)":
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 5000
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 10000
  threadpool:
    default:
      coreSize: 100

ribbon:
  ConnectTimeout: 50000
  ReadTimeout: 30000

配置文件中單獨配置了findUserByUsername的Timeout時間,其他配置可以仿照這種方式,但是要注意的是每一個Feign client對應的是一個threadPool所以不能針對每個command配置不同的threadPool.但是Threadpool.default.coreSize中的default可以改成serviceId,如果有多個服務的話可以配置不一樣的threadPool.

5.Hystrix dashboard, Hystrix turbine

在使用turbine中的時候需要單獨起一個服務,並且使用@EnableTurbine開啓.需要注意的點是使用的cloud版本最好和微服務中的cloud一致,因爲較早版本使用url /hystrix.stream 收集信息,而較新的版本使用/actuator/hystrix.stream收集信息.如果兩邊不一致的話會導致404錯誤.下面附上代碼:

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.example</groupId>
	<artifactId>demo</artifactId>
	<version>0.0.1-SNAPSHOT</version>
	<packaging>jar</packaging>

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

	<parent>
		<groupId>org.springframework.boot</groupId>
		<artifactId>spring-boot-starter-parent</artifactId>
		<version>1.5.3.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>Edgware.SR5</spring-cloud.version>
	</properties>

	<dependencies>

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

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

		<dependency>
			<groupId>org.springframework.cloud</groupId>
			<artifactId>spring-cloud-netflix-eureka-client</artifactId>
			<version>1.3.0.RELEASE</version>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-actuator</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>spring-milestones</id>
			<name>Spring Milestones</name>
			<url>https://repo.spring.io/milestone</url>
			<snapshots>
				<enabled>false</enabled>
			</snapshots>
		</repository>
	</repositories>


</project>

啓動類:

package com.example.demo;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
import org.springframework.cloud.netflix.turbine.EnableTurbine;

@SpringBootApplication
@EnableHystrixDashboard
@EnableTurbine
@EnableDiscoveryClient
public class DemoApplication {

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

配置文件:

spring:
  application:
    name: turbine

server:
  port: 9090


eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
    registerWithEureka: true
  instance:
    preferIpAddress: true
    instance-id: ${spring.cloud.client.ipAddress}:${server.port}
turbine:
  aggregator:
    clusterConfig: LEARN-HYSTRIX
  appConfig: learn-hystrix

注意:

  1. 微服務註冊到Eureka中的時候最好的Instance-id爲Ip+端口號,否則在收集信息的時候會有錯誤
  2. appConfig爲服務列表多個用逗號連接
  3. clusterConfig: 爲監控聚合的url,多個話用逗號連接,舉個例子:http://localhost:9090/turbine.stream?cluster=LEARN-HYSTRIX
  4. 進入dashboard url http://localhost:{port}/hystrix
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章