億級流量網站架構核心技術中Hystix的線程池隔離詳解

 

咱們來看下面的測試代碼:java

首先是註冊中心代碼web

pom.xmlspring

<?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.tuling.cloud</groupId>
  <artifactId>microservice-eureka-server</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <!-- 引入spring boot的依賴 -->
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.9.RELEASE</version>
  </parent>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>1.8</java.version>
  </properties>

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

  <!-- 引入spring cloud的依賴 -->
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Edgware.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <!-- 添加spring-boot的maven插件 -->
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

 

啓動類的代碼sql

package com.tuling.cloud.study;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;

/**
 * 使用Eureka作服務發現.
 */
@SpringBootApplication
@EnableEurekaServer
public class EurekaApplication {
  public static void main(String[] args) {
    SpringApplication.run(EurekaApplication.class, args);
  }
}

 

接下來服務提供者user的代碼數據庫

<?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.tuling.cloud</groupId>
  <artifactId>microservice-provider-user</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <!-- 引入spring boot的依賴 -->
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.9.RELEASE</version>
  </parent>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>1.8</java.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-data-jpa</artifactId>
    </dependency>
    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</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-netflix-eureka-client</artifactId>
    </dependency>
    
    <!-- spring boot admin監控客戶端依賴 -->
    <dependency>
      <groupId>de.codecentric</groupId>
      <artifactId>spring-boot-admin-starter-client</artifactId>
      <version>1.5.6</version>
    </dependency>
    
     <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-sleuth</artifactId>
    </dependency>
        <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-sleuth-zipkin</artifactId>
    </dependency>
    
  </dependencies>

  <!-- 引入spring cloud的依賴 -->
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Edgware.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <!-- 添加spring-boot的maven插件 -->
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

 

這裏使用了h2數據庫,數據庫的腳本以下apache

drop table user if exists;
create table user (id bigint generated by default as identity, username varchar(40), name varchar(20), age int(3), balance decimal(10,2), primary key (id));

 

insert into user (id, username, name, age, balance) values (1, 'account1', '張三', 20, 100.00);
insert into user (id, username, name, age, balance) values (2, 'account2', '李四', 28, 180.00);
insert into user (id, username, name, age, balance) values (3, 'account3', '王五', 32, 280.00);

 

application.yml

 

server:
  port: 8003
spring:
  application:
    name: microservice-provider-user
  zipkin:
    base-url: http://localhost:9411
  sleuth:
    sampler:
      percentage: 1.0  
  boot:
    admin:
      url: http://localhost:9999        # spring boot admin服務端地址,蒐集客戶端監控數據
  jpa:
    generate-ddl: false
    show-sql: true
    hibernate:
      ddl-auto: none
  datasource:                           # 指定數據源
    platform: h2                        # 指定數據源類型
    schema: classpath:schema.sql        # 指定h2數據庫的建表腳本
    data: classpath:data.sql            # 指定h2數據庫的數據腳本
logging:                                # 配置日誌級別,讓hibernate打印出執行的SQL
  level:
    root: INFO
    org.hibernate: INFO
    org.hibernate.type.descriptor.sql.BasicBinder: TRACE
    org.hibernate.type.descriptor.sql.BasicExtractor: TRACE
    org.springframework.cloud.sleuth: DEBUG  
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
management:
  security:
    enabled: false  #關掉安全認證
  port: 8886  #管理端口調整成8888,獨立的端口能夠作安全控制
  context-path: /monitor  #actuator的訪問路徑
  health:
    mail:
      enabled: false
    

 

UserRepository緩存

package com.tuling.cloud.study.repository;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.stereotype.Repository;

import com.tuling.cloud.study.entity.User;

@Repository
public interface UserRepository extends JpaRepository<User, Long> {
}

 

User安全

package com.tuling.cloud.study.entity;

import java.math.BigDecimal;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

@Entity
public class User {
  @Id
  @GeneratedValue(strategy = GenerationType.AUTO)
  private Long id;
  @Column
  private String username;
  @Column
  private String name;
  @Column
  private Integer age;
  @Column
  private BigDecimal balance;

  public Long getId() {
    return this.id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String getUsername() {
    return this.username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public String getName() {
    return this.name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public Integer getAge() {
    return this.age;
  }

  public void setAge(Integer age) {
    this.age = age;
  }

  public BigDecimal getBalance() {
    return this.balance;
  }

  public void setBalance(BigDecimal balance) {
    this.balance = balance;
  }

}

 

UserController併發

package com.tuling.cloud.study.controller;

import org.apache.log4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.client.serviceregistry.Registration;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import com.tuling.cloud.study.entity.User;
import com.tuling.cloud.study.repository.UserRepository;

@RestController
public class UserController {
    
  private final Logger logger = Logger.getLogger(getClass());
    
  @Autowired
  private UserRepository userRepository;
  @Autowired
  private Registration registration;
  

@GetMapping(
"/{id}") public User findById(@PathVariable Long id) throws Exception { logger.info("用戶中心接口:查詢用戶"+ id +"信息"); Thread.sleep(3000); User findOne = userRepository.findOne(id); return findOne; } @GetMapping("/getIpAndPort") public String findById() { return registration.getHost() + ":" + registration.getPort(); } @GetMapping("/testException") public User testException() throws Exception { Thread.sleep(2000); throw new RuntimeException("userService throw new RuntimeException "); } @RequestMapping(value = "/aa", method = RequestMethod.GET) public String aa(){ try { Thread.sleep(3000); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } return "aa is sb"; } }

 啓動類:app

ProviderUserApplication

package com.tuling.cloud.study;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;

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

 咱們來看客戶端是否feign來調用user,實現熔斷降級

pom.xml

<?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.tuling.cloud</groupId>
  <artifactId>microservice-consumer-order-feign-hystrix-fallback</artifactId>
  <version>0.0.1-SNAPSHOT</version>
  <packaging>jar</packaging>

  <!-- 引入spring boot的依賴 -->
  <parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>1.5.9.RELEASE</version>
  </parent>

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <java.version>1.8</java.version>
  </properties>

  <dependencies>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-starter-web</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-netflix-eureka-client</artifactId>
    </dependency>

    <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-starter-openfeign</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-sleuth</artifactId>
    </dependency>
        <dependency>
      <groupId>org.springframework.cloud</groupId>
      <artifactId>spring-cloud-sleuth-zipkin</artifactId>
    </dependency>
    
  </dependencies>

  <!-- 引入spring cloud的依賴 -->
  <dependencyManagement>
    <dependencies>
      <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>Edgware.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
    </dependencies>
  </dependencyManagement>

  <!-- 添加spring-boot的maven插件 -->
  <build>
    <plugins>
      <plugin>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-maven-plugin</artifactId>
      </plugin>
    </plugins>
  </build>
</project>

 

UserFeignClient

package com.tuling.cloud.study.user.feign;

import org.springframework.cloud.netflix.feign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

import com.tuling.cloud.config.FeignDisableHystrixConfiguration;
import com.tuling.cloud.study.user.entity.User;

/**
 * Feign的fallback測試
 * 使用@FeignClient的fallback屬性指定回退類
 */ @FeignClient(name = "microservice-provider-user", fallback = FeignClientFallback.class) public interface UserFeignClient {
  @RequestMapping(value = "/{id}", method = RequestMethod.GET)
  public User findById(@PathVariable("id") Long id);
  
  @RequestMapping(value = "/aa", method = RequestMethod.GET)
  public String  aa();
  
}

/**
 * 回退類FeignClientFallback需實現Feign Client接口
 * FeignClientFallback也能夠是public class,沒有區別
 */
@Component
class FeignClientFallback implements UserFeignClient {
  @Override
  public User findById(Long id) {
    User user = new User();
    user.setId(-1L);
    user.setUsername("默認用戶");
    return user;
  }
  
  public User findById(Throwable e) {
      System.out.println("異常信息爲:"+e.toString());
        User user = new User();
        user.setId(-1L);
        user.setUsername("默認用戶");
        return user;
      }

@Override
public String aa() {
    // TODO Auto-generated method stub
    return "fallback aaaaa";
}
}

 經過定了一個fegin接口,改接口中存在兩個方法,使用兩個遠程調用的方法,而後須要給改方法設置降級的方法,其餘這裏對線程沒有作任何設置

兩個接口正常訪問效果以下

 User

package com.tuling.cloud.study.user.entity;

import java.math.BigDecimal;

public class User {
  private Long id;
  private String username;
  private String name;
  private Integer age;
  private BigDecimal balance;

  public Long getId() {
    return this.id;
  }

  public void setId(Long id) {
    this.id = id;
  }

  public String getUsername() {
    return this.username;
  }

  public void setUsername(String username) {
    this.username = username;
  }

  public String getName() {
    return this.name;
  }

  public void setName(String name) {
    this.name = name;
  }

  public Integer getAge() {
    return this.age;
  }

  public void setAge(Integer age) {
    this.age = age;
  }

  public BigDecimal getBalance() {
    return this.balance;
  }

  public void setBalance(BigDecimal balance) {
    this.balance = balance;
  }
}

 

OrderController

package com.tuling.cloud.study.user.controller;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RestController;

import com.tuling.cloud.study.user.entity.User;
import com.tuling.cloud.study.user.feign.UserFeignClient;

@RestController
public class OrderController {
  @Autowired
  private UserFeignClient userFeignClient;

  @GetMapping("/user/{id}")
  public User findById(@PathVariable Long id) {
      
      
     // throw new RuntimeException("sadkjdsa,,kd");
           return userFeignClient.findById(id);
        
 
  }
  
  @GetMapping("/aa")
  public String findById1() {
    return userFeignClient.aa();
  }
}

 

ConsumerOrderApplication啓動類的代碼以下

package com.tuling.cloud.study;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.discovery.EnableDiscoveryClient;
import org.springframework.cloud.netflix.feign.EnableFeignClients;

@EnableDiscoveryClient
@SpringBootApplication
@EnableFeignClients
public class ConsumerOrderApplication {
  public static void main(String[] args) {
    SpringApplication.run(ConsumerOrderApplication.class, args);
  }
}

 

接下來咱們來看最重要的文件配置

application.yml

server:
  port: 8020
spring:
  application:
    name: microservice-consumer-order
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true hystrix: command: default: execution: isolation: thread: timeoutInMilliseconds: 10000
  #threadpool:
    #default:
      #coreSize: 20 #併發執行的最大線程數,默認10     
feign: client: config: default: connectTimeout: 5000 readTimeout: 5000
  hystrix:
    enabled: true

 

這裏要強調下,由於user中服務提供者中設置了Thread.sleep 3秒,這裏客戶端調用遠程user不要超時,咱們要設置Hystix超時時間爲10秒,保證和Hystix調用的超時大於睡眠時間,不拋出異常

這裏要按照上面兩個黃色進行設置,fegin設置Hystix的超時時間,也要設置feign客戶端的讀取時間,兩個設置採用效果

接下來咱們,進行測試

咱們打開兩個jemter

 

 第一個jemetre開啓15個線程去訪問http://localhost:8020/aa

第二個jemetr,去訪問http://localhost:8020/user/1/

默認order服務消費方這裏沒有作任何設置,默認線程池的大小是10

咱們先點擊點一個jmeter,而後馬上點擊第二個jmeter,咱們拉看下打印的結果以下

fallback aaaaa
fallback aaaaa
fallback aaaaa
fallback aaaaa
fallback aaaaa
aa is sb
aa is sb
aa is sb
aa is sb
aa is sb
aa is sb
aa is sb
aa is sb
aa is sb

{"id":-1,"username":"默認用戶","name":null,"age":null,"balance":null}
{"id":-1,"username":"默認用戶","name":null,"age":null,"balance":null}
{"id":-1,"username":"默認用戶","name":null,"age":null,"balance":null}
{"id":-1,"username":"默認用戶","name":null,"age":null,"balance":null}
{"id":-1,"username":"默認用戶","name":null,"age":null,"balance":null}
{"id":-1,"username":"默認用戶","name":null,"age":null,"balance":null}
{"id":-1,"username":"默認用戶","name":null,"age":null,"balance":null}
{"id":-1,"username":"默認用戶","name":null,"age":null,"balance":null}
{"id":-1,"username":"默認用戶","name":null,"age":null,"balance":null}
{"id":-1,"username":"默認用戶","name":null,"age":null,"balance":null}
{"id":-1,"username":"默認用戶","name":null,"age":null,"balance":null}
{"id":-1,"username":"默認用戶","name":null,"age":null,"balance":null}
{"id":-1,"username":"默認用戶","name":null,"age":null,"balance":null}
{"id":-1,"username":"默認用戶","name":null,"age":null,"balance":null}
{"id":-1,"username":"默認用戶","name":null,"age":null,"balance":null}
{"id":-1,"username":"默認用戶","name":null,"age":null,"balance":null}
{"id":-1,"username":"默認用戶","name":null,"age":null,"balance":null}

 

咱們能夠看到結果,第一個請求訪問aa當前線程池線程大小是10,全部15個請求中10個線程執行訪問,5個請求由於沒有線程資源直接被拒絕,走降級的方法

第二個請求訪問usr/1接口,由於此時和第一個請求共享同一個線程池。第一個請求訪問aa尚未結束,第二個訪問的15個請求,直接被拒絕

結論:上面feign接口遠程調用時,默認狀況下同一個feign接口裏面的方法在同一時間共享同一個線程池,線程池的大小默認是10 ,默認共享的線程池爲改feign接口的類名

另一個fegin接口裏面的方法共享另一個線程池,達到線程隔離的效果

接下來,咱們來看線程池的三個參數,咱們能夠調整Hystix默認的線程池的最大併發數

hystrix:
  threadpool:
    default:
      coreSize: 200 #併發執行的最大線程數,默認10
      maxQueueSize: 1000 #BlockingQueue的最大隊列數,默認值-1
      queueSizeRejectionThreshold: 800 #

 

這裏上面coreSize,咱們設置線程池的大小是200,而後還要兩個值maxQueueSize和queueSizeRejectionThreshold,這裏要重點強調下

maxQueueSize和queueSizeRejectionThreshold,若是配置queueSizeRejectionThreshold的值大於maxQueueSize的值,那麼queueSizeRejectionThreshold值沒有生效,以maxQueueSize的爲準,若是

queueSizeRejectionThreshold的值小於maxQueueSize的值,以queueSizeRejectionThreshold的爲準

上面queueSizeRejectionThreshold的值小於maxQueueSize的值,以queueSizeRejectionThreshold的爲準

queueSizeRejectionThreshold是對隊列大小進行限制的,若是線程池隊列大小是50,queueSizeRejectionThreshold大小設置爲30,那麼放在隊列中有效的請求就是30

上面default表示對當前jvm進程中國的全部的fegin接口都設置線程池的大小是200,如今咱們要單獨對某個feign接口設置線程池的大小能夠不,答案固然能夠

server:
  port: 8020
spring:
  application:
    name: microservice-consumer-order
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 10000
  threadpool:
    default:
      coreSize: 15 #併發執行的最大線程數,默認10
    microservice-provider-user: coreSize: 20 #併發執行的最大線程數,默認10 maxQueueSize: 1000 #BlockingQueue的最大隊列數,默認值-1 queueSizeRejectionThreshold: 800 #即便maxQueueSize沒有達到,達到queueSizeRejectionThreshold該值後,請求也會被拒絕,默認值5        
feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
  hystrix:
    enabled: true

 

@FeignClient(name = "microservice-provider-user", fallback = FeignClientFallback.class),上面就是單獨對訪問microservice-provider-user整個feign客戶端設置共享的線程池大小爲20,隊列大小爲1000

 相關配置列表

 

總結:能夠給具體的FeignClient接口設置線程池的大小,FeignCleint裏面的方法共享一個線程池

 

接下來咱們講講單獨爲FeignClient接口下面的某個方法的調用設置超時時間

上面的HysComandKey就是類名#方法名(參數)例如: UserFeignClient#findById(Long),具體能夠在Hystix監控數據流中能夠查看

 

 咱們來看具體的參數配置

server:
  port: 8020
spring:
  application:
    name: microservice-consumer-order
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 10000 UserFeignClient#findById(Long): circuitBreaker: forceOpen: false execution: isolation: thread: timeoutInMilliseconds: 1000           
                  
  threadpool:
    default:
      coreSize: 15 #併發執行的最大線程數,默認10
    microservice-provider-user:
      coreSize: 20 #併發執行的最大線程數,默認10  
      maxQueueSize: 1000 #BlockingQueue的最大隊列數,默認值-1
      queueSizeRejectionThreshold: 800 #即便maxQueueSize沒有達到,達到queueSizeRejectionThreshold該值後,請求也會被拒絕,默認值5        
feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
  hystrix:
    enabled: true

 咱們設置UserFeignClient#findById(Long)讓熔斷器處於開啓狀態,訪問改訪問的時候調用的超時時間爲1秒

默認狀況下Hystix是開啓超時時間的功能,上面我設置了UserFeignClient#findById(Long)方法調用的超時時間是1秒,若是爲要禁用改功能如何實現了

改功能表示禁用Hystix的超時功能機制,默認狀況下Hystix是要進行超時功能的,若是要取消該功能,參數設置爲false就能夠了,改功能建議爲默認值

server:
  port: 8020
spring:
  application:
    name: microservice-consumer-order
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 10000 UserFeignClient#findById(Long): circuitBreaker: forceOpen: false execution: isolation: thread: timeoutInMilliseconds: 1000 timeout: enabled: false
                       
                  
  threadpool:
    default:
      coreSize: 15 #併發執行的最大線程數,默認10
    microservice-provider-user:
      coreSize: 20 #併發執行的最大線程數,默認10  
      maxQueueSize: 1000 #BlockingQueue的最大隊列數,默認值-1
      queueSizeRejectionThreshold: 800 #即便maxQueueSize沒有達到,達到queueSizeRejectionThreshold該值後,請求也會被拒絕,默認值5        
feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
  hystrix:
    enabled: true

此外,咱們也能夠針對UserFeignClient#findById(Long)作到熔斷器參數的設置

 

咱們舉例子來看下

第一:咱們當Hystix訪問超時的時候,咱們進行使用fallback走降級方法的功能,程序會直接拋出異常

server:
  port: 8020
spring:
  application:
    name: microservice-consumer-order
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 10000         
    UserFeignClient#findById(Long):
      circuitBreaker: 
        forceOpen: false 
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 1000
        timeout: 
          enabled: true fallback: enabled: false    
                       
                  
  threadpool:
    default:
      coreSize: 15 #併發執行的最大線程數,默認10
    microservice-provider-user:
      coreSize: 20 #併發執行的最大線程數,默認10  
      maxQueueSize: 1000 #BlockingQueue的最大隊列數,默認值-1
      queueSizeRejectionThreshold: 800 #即便maxQueueSize沒有達到,達到queueSizeRejectionThreshold該值後,請求也會被拒絕,默認值5        
feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
  hystrix:
    enabled: true

 

 這個時候訪問的時候,當訪問超時了,程序不會走默認的降級方法,直接拋出異常

接下來,咱們能夠爲UserFeignClient#findById(Long)作熔斷參數的具體設置

server:
  port: 8020
spring:
  application:
    name: microservice-consumer-order
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
hystrix:
  command:
    default:
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 10000 UserFeignClient#findById(Long): circuitBreaker: forceOpen: false requestVolumeThreshold: 10 sleepWindowInMilliseconds: 5 errorThresholdPercentage: 50 
      execution:
        isolation:
          thread:
            timeoutInMilliseconds: 1000
        timeout: 
          enabled: true
      fallback: 
        enabled: true    
                       
                  
  threadpool:
    default:
      coreSize: 15 #併發執行的最大線程數,默認10
    microservice-provider-user:
      coreSize: 20 #併發執行的最大線程數,默認10  
      maxQueueSize: 1000 #BlockingQueue的最大隊列數,默認值-1
      queueSizeRejectionThreshold: 800 #即便maxQueueSize沒有達到,達到queueSizeRejectionThreshold該值後,請求也會被拒絕,默認值5        
feign:
  client:
    config:
      default:
        connectTimeout: 5000
        readTimeout: 5000
  hystrix:
    enabled: true

 此外還有其餘差數的設置:例如設置統計時間窗口的設置、時間窗口內採用桶數目的設置等

Execution:用來控制HystrixCommand.run()的執行

execution.isolation.strategy:該屬性用來設置HystrixCommand.run()執行的隔離策略。默認爲THREAD。
execution.isolation.thread.timeoutInMilliseconds:該屬性用來配置HystrixCommand執行的超時時間,單位爲毫秒。
execution.timeout.enabled:該屬性用來配置HystrixCommand.run()的執行是否啓用超時時間。默認爲true。
execution.isolation.thread.interruptOnTimeout:該屬性用來配置當HystrixCommand.run()執行超時的時候是否要它中斷。
execution.isolation.thread.interruptOnCancel:該屬性用來配置當HystrixCommand.run()執行取消時是否要它中斷。
execution.isolation.semaphore.maxConcurrentRequests:當HystrixCommand命令的隔離策略使用信號量時,該屬性用來配置信號量的大小。當最大併發請求達到該設置值時,後續的請求將被拒絕。
2 Fallback:用來控制HystrixCommand.getFallback()的執行

fallback.isolation.semaphore.maxConcurrentRequests:該屬性用來設置從調用線程中容許HystrixCommand.getFallback()方法執行的最大併發請求數。當達到最大併發請求時,後續的請求將會被拒絕並拋出異常。
fallback.enabled:該屬性用來設置服務降級策略是否啓用,默認是true。若是設置爲false,當請求失敗或者拒絕發生時,將不會調用HystrixCommand.getFallback()來執行服務降級邏輯。
3 Circuit Breaker:用來控制HystrixCircuitBreaker的行爲。

circuitBreaker.enabled:肯定當服務請求命令失敗時,是否使用斷路器來跟蹤其健康指標和熔斷請求。默認爲true。
circuitBreaker.requestVolumeThreshold:用來設置在滾動時間窗中,斷路器熔斷的最小請求數。例如,默認該值爲20的時候,若是滾動時間窗(默認10秒)內僅收到19個請求,即便這19個請求都失敗了,斷路器也不會打開。
circuitBreaker.sleepWindowInMilliseconds:用來設置當斷路器打開以後的休眠時間窗。休眠時間窗結束以後,會將斷路器設置爲「半開」狀態,嘗試熔斷的請求命令,若是依然時候就將斷路器繼續設置爲「打開」狀態,若是成功,就設置爲「關閉」狀態。
circuitBreaker.errorThresholdPercentage:該屬性用來設置斷路器打開的錯誤百分比條件。默認值爲50,表示在滾動時間窗中,在請求值超過requestVolumeThreshold閾值的前提下,若是錯誤請求數百分比超過50,就把斷路器設置爲「打開」狀態,不然就設置爲「關閉」狀態。
circuitBreaker.forceOpen:該屬性默認爲false。若是該屬性設置爲true,斷路器將強制進入「打開」狀態,它會拒絕全部請求。該屬性優於forceClosed屬性。
circuitBreaker.forceClosed:該屬性默認爲false。若是該屬性設置爲true,斷路器強制進入「關閉」狀態,它會接收全部請求。若是forceOpen屬性爲true,該屬性不生效。
4 Metrics:該屬性與HystrixCommand和HystrixObservableCommand執行種捕獲的指標相關。

metrics.rollingStats.timeInMilliseconds:該屬性用來設置滾動時間窗的長度,單位爲毫秒。該時間用於斷路器判斷健康度時須要收集信息的持續時間。斷路器在收集指標信息時會根據設置的時間窗長度拆分紅多個桶來累計各度量值,每一個桶記錄了一段時間的採集指標。例如,當爲默認值10000毫秒時,斷路器默認將其分紅10個桶,每一個桶記錄1000毫秒內的指標信息。
metrics.rollingStats.numBuckets:用來設置滾動時間窗統計指標信息時劃分「桶」的數量。默認值爲10。
metrics.rollingPercentile.enabled:用來設置對命令執行延遲是否使用百分位數來跟蹤和計算。默認爲true,若是設置爲false,那麼全部的概要統計都將返回-1。
metrics.rollingPercentile.timeInMilliseconds:用來設置百分位統計的滾動窗口的持續時間,單位爲毫秒。
metrics.rollingPercentile.numBuckets:用來設置百分位統計滾動窗口中使用桶的數量。
metrics.rollingPercentile.bucketSize:用來設置每一個「桶」中保留的最大執行數。
metrics.healthSnapshot.intervalInMilliseconds:用來設置採集影響斷路器狀態的健康快照的間隔等待時間。
5 Request Context:涉及HystrixCommand使用HystrixRequestContext的設置。

requestCache.enabled:用來配置是否開啓請求緩存。
requestLog.enabled:用來設置HystrixCommand的執行和事件是否打印到日誌的HystrixRequestLog中。
二 相關配置列表

 

 

 

 

 

二 相關配置列表

相關文章
相關標籤/搜索