微服務Spring Cloud (四)服務熔斷 Hystrix Dashboard Turbin

轉載請表明出處 https://blog.csdn.net/Amor_Leo/article/details/87879522 謝謝

Spring Cloud Hystrix概述

在微服務中,各個微服務之間通過網絡進行通信,從而支撐起整個應用系統,所以,各個微服務之間不可避免的存在耦合依賴關係。但任何的服務應用實例都不可能永遠的健康或網絡不可能永遠的都相安無事,所以一旦某個服務或局部業務發生了故障,會導致系統的不可用,我們知道當故障累積到一定程度就會造成系統層面的災害,也就是級聯故障,也叫雪崩效應,Spring Cloud Hystrix可以進行FallBack操作來服務降級,實現一個fallback方法, 當請求後端服務出現異常的時候, 可以使用fallback方法返回的值。
Spring Cloud Hystrix實現了斷路器、線路隔離等一系列服務保護功能。它也是基於 Netflix 的開源框架 Hystrix 實現的,該框架的目標在於通過控制那些訪問遠程系統、服務和第三方庫的節點,從而對延遲和故障提供更強大的容錯能力。Hystrix 具備服務降級、服務熔斷、線程和信號隔離、請求緩存、請求合併以及服務監控等強大功能。

  1. 請求熔斷: 當Hystrix Command請求後端服務失敗數量超過一定比例(默認50%), 斷路器會切換到開路狀態(Open). 這時所有請求會直接失敗而不會發送到後端服務. 斷路器保持在開路狀態一段時間後(默認5秒), 自動切換到半開路狀態(HALF-OPEN).這時會判斷下一次請求的返回情況, 如果請求成功, 斷路器切回閉路狀態(CLOSED), 否則重新切換到開路狀態(OPEN). Hystrix的斷路器就像我們家庭電路中的保險絲, 一旦後端服務不可用, 斷路器會直接切斷請求鏈, 避免發送大量無效請求影響系統吞吐量, 並且斷路器有自我檢測並恢復的能力.
  2. 服務降級:Fallback相當於是降級操作. 對於查詢操作, 我們可以實現一個fallback方法, 當請求後端服務出現異常的時候, 可以使用fallback方法返回的值. fallback方法的返回值一般是設置的默認值或者來自緩存.告知後面的請求服務不可用了,不要再來了。

Spring Cloud Hystrix搭建

與Ribbon整合

  • pom
  <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-netflix-hystrix</artifactId>
  </dependency>
  • yml
spring:
  application:
    name: consumer-service
server:
  port: 8080
eureka:
  client:
    service‐url:
      defaultZone: http://localhost:8761/eureka
  instance:
    prefer‐ip‐address: true  #訪問路徑可以顯示ip地址
  • Application類
@EnableDiscoveryClient
@SpringBootApplication
@EnableCircuitBreaker  //開啓Hystrix
public class ConsumerApplication {
  @Bean
  @LoadBalanced
  public RestTemplate restTemplate() {
    return new RestTemplate();
  }

  public static void main(String[] args) {
    SpringApplication.run(ConsumerMovieApplication.class, args);
  }
}
  • Controller
  	@Autowired
    private RestTemplate restTemplate;

	@HystrixCommand(fallbackMethod = "getDefaultUser")
	@GetMapping("/get/provider/test")
	public String rpc() {                  
		String forObject = restTemplate.getForObject("http://PROVIDER-SERVICE/test", String.class);
		return forObject;
	}
	
	private String getDefaultUser() {
        System.out.println("熔斷,默認回調函數");
        return "Hystrix熔斷";
    }

與Feign整合

  • pom
 <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>
  • yml
server:
  port: 8010
spring:
  application:
    name: consumer-service
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
feign:
  hystrix:
    enabled: true
# 請務必注意:從Spring Cloud Dalston開始,Feign默認是不開啓Hystrix的。
# 因此,如使用Dalston(包括)之後請務必額外設置屬性:feign.hystrix.enabled=true,否則斷路器不會生效。
# 而,Spring Cloud Angel/Brixton/Camden中,Feign默認都是開啓Hystrix的。無需設置該屬性。
  • Application類上
@EnableDiscoveryClient
@EnableFeignClients  // 開啓Feign
  • 自定義Controller
@RestController
public class ConsumerController {
  @Autowired
  private FeignClient feignClient;

  @GetMapping("/{id}")
  public String findById(@PathVariable Long id) {
    return this.feignClient.findById(id);
  }

Fallback回退

  • 回退類配置
/**
 * 回退類FeignClientFallback需實現Feign Client接口
 */
@Component
public class FeignClientFallback implements FeignClient {
  @Override
  public String findById(Long id) {
    return "Hystrix 熔斷"+id;
  }
}
  • 自定義Feign接口
@FeignClient(name = "provider-service", fallback = FeignClientFallback.class)
public interface FeignClient {
	
    @RequestMapping(value = "/provider/{id}", method = RequestMethod.GET)
    public String findById(@PathVariable("id") Long id);
}

通過FallBack Factory檢查回退原因

  • 自定義Feign接口
@FeignClient(name = "provider-service", fallbackFactory = FeignClientFallbackFactory.class)
public interface FeignClient {
	
    @RequestMapping(value = "/provider/{id}", method = RequestMethod.GET)
    public String findById(@PathVariable("id") Long id);
}
  • FallbackFactory 配置
/**
 * FeignClient的fallbackFactory類,該類需實現FallbackFactory接口,並覆寫create方法
 */
@Component
class FeignClientFallbackFactory implements FallbackFactory<FeignClient> {

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

  @Override
  public FeignClient create(Throwable cause) {
    return new FeignClient() {
      @Override
      public String findById(Long id) {
        // 日誌最好放在各個fallback方法中,而不要直接放在create方法中.
        // 否則在引用啓動時,就會打印該日誌
        FeignClientFallbackFactory.LOGGER.info("fallback; reason was:", cause);
        
        return  "Hystrix 熔斷"+id;
      }
    };
  }
}

Feign的Hystrix的監控:

  • pom
  <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.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
  </dependency>
  • Application類上
@EnableDiscoveryClient
@EnableFeignClients
@EnableCircuitBreaker

使用dashboard可視化

  • pom
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</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>
    <!--Feign支持Hystrix的監控-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    <!--Hystrix的監控可視化界面-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    </dependency>
  • yml
server:
  port: 8010
spring:
  application:
    name: consumer-service
eureka:
  client:
    serviceUrl:
      defaultZone: http://localhost:8761/eureka/
  instance:
    prefer-ip-address: true
feign:
  hystrix:
    enabled: true   #開啓熔斷器
management:
  endpoints:
    web:
      exposure:
        include: "*"  #因爲springboot2.1.必須加上,支持訪問/actuator/hystrix.stream
  • Application類上
@EnableDiscoveryClient
@EnableFeignClients
@EnableHystrixDashboard
@EnableCircuitBreaker
  • 自定義Controller
@RestController
public class ConsumerController {
  @Autowired
  private FeignClient feignClient;

  @GetMapping("/{id}")
  public String findById(@PathVariable Long id) {
    return this.feignClient.findById(id);
  }
  • 回退類配置
/**
 * 回退類FeignClientFallback需實現Feign Client接口
 */
@Component
public class FeignClientFallback implements FeignClient {
  @Override
  public String findById(Long id) {
    return "Hystrix 熔斷"+id;
  }
}
  • 自定義Feign接口
@FeignClient(name = "provider-service", fallback = FeignClientFallback.class)
public interface FeignClient {
	
    @RequestMapping(value = "/provider/{id}", method = RequestMethod.GET)
    public String findById(@PathVariable("id") Long id);
}

http://192.168.0.1:8010/hystrix/ 進入可視化界面,輸入: http://192.168.0.1:8010/actuator/hystrix.stream

Turbin

  • 消費者
    • pom
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <!--Hystrix的監控可視化界面-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    </dependency>
    
    • yml
    management:
      endpoints:
        web:
          exposure:
            include: "*"  #因爲springboot2.1.必須加上,支持訪問/actuator/hystrix.stream
    
    • Application類上
    @EnableCircuitBreaker
    
  • Turbin Server
    • pom
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</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-starter-turbine</artifactId>
    </dependency>
    
    • yml
    spring:
      application:
        name: dashboard-turbine
    server:
      port: 8020
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:8761/eureka/
      instance:
        prefer-ip-address: true
    turbine:
      app-config: consumer-service # 配置Eureka中的serviceId列表,表明監控哪些服務
      aggregator:
        clusterConfig:  default
      cluster-name-expression: new String("default")  # 表示集羣的名字爲default,當服務數量非常多的時候,可以啓動多個Turbine服務來構建不同的聚合集羣
      combine-host-port: true # 表示同一主機上的服務通過host和port的組合來進行區分,默認情況下是使用host來區分,這樣會使本地調試有問題
    management:
      endpoints:
        web:
          exposure:
            include: "*"
    
    • Application類上
    @EnableTurbine
    
    訪問 : http://192.168.0.1:8020/turbine.stream進入頁面

Turbin+Dashboard

  • 消費者(Feign+熔斷器)
    • pom
     <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</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>
    <!--Feign支持Hystrix的監控-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    <!--Hystrix的監控可視化界面-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    </dependency>
    
    • yml
    server:
      port: 8010
    spring:
      application:
        name: consumer-service
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:8761/eureka/
      instance:
        prefer-ip-address: true
    feign:
      hystrix:
        enabled: true   #開啓熔斷器
    management:
      endpoints:
        web:
          exposure:
            include: "*"  #因爲springboot2.1.必須加上,支持訪問/actuator/hystrix.stream
    
    • Application類上
    @EnableDiscoveryClient
    @EnableFeignClients
    @EnableHystrixDashboard
    @EnableCircuitBreaker
    
  • dashboard+turbine server:
    • pom
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</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-starter-turbine</artifactId>
    </dependency>
    
    • yml
    spring:
      application:
        name: dashboard-turbine-server
    server:
      port: 8020
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:8761/eureka/
      instance:
        prefer-ip-address: true
    turbine:
      app-config: consumer-service # 配置Eureka中的serviceId列表,表明監控哪些服務
      aggregator:
        clusterConfig:  default
      cluster-name-expression: new String("default")  # 表示集羣的名字爲default,當服務數量非常多的時候,可以啓動多個Turbine服務來構建不同的聚合集羣
      combine-host-port: true # 表示同一主機上的服務通過host和port的組合來進行區分,默認情況下是使用host來區分,這樣會使本地調試有問題
    management:
      endpoints:
        web:
          exposure:
            include: "*"
    
    • Application類上
    @EnableHystrixDashboard
    @EnableTurbine
    

可以直接訪問 http://192.168.0.1:8020/turbine.stream
也可以 http://192.168.0.1:8020/hystrix/ 再輸入 http://192.168.0.1:8020/turbine.stream
也可以通過消費者 http://192.168.0.1:8010/hystrix/ 再輸入 http://192.168.0.1:8020/turbine.stream

Turbine+Dashboard+RabbitMQ

  • 消費者
    • pom
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</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>
    <!--Hystrix的監控可視化界面-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    </dependency>
    <!--Feign支持Hystrix的監控-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
    </dependency>
    <!--MQ-->	
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-netflix-hystrix-stream</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
    </dependency>
    
    • yml
    server:
      port: 8010
    spring:
      application:
        name: consumer-service
      rabbitmq:
        host: 192.168.0.111
        port: 5672
        username: admin
        password: admin
    eureka:
      client:
        serviceUrl:
          defaultZone: http://localhost:8761/eureka/
      instance:
        prefer-ip-address: true
    feign:
      hystrix:
        enabled: true
    management:
      endpoints:
        web:
          exposure:
            include: "*"
    
    • Application類上
    @EnableDiscoveryClient
    @EnableFeignClients
    @EnableHystrixDashboard
    @EnableCircuitBreaker
    
  • turbine+mq+dashboard server
    • pom
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</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-stream</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-stream-rabbit</artifactId>
    </dependency>
    
    • yml
    server:
      port: 8020
    spring:
      application:
        name: turbine-server
      rabbitmq:
        host: 192.168.0.111
        port: 5672
        username: admin
        password: admin
    eureka:
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/
      instance:
        prefer-ip-address: true
    management:
      endpoints:
        web:
          exposure:
            include: "*"
    
    • Application類上
    @EnableTurbineStream
    @EnableHystrixDashboard
    

直接訪問 http://192.168.0.1:8020/turbine.stream
先訪問 http://192.168.0.1:8020/hystrix/ 再輸入 http://192.168.0.1:8020/turbine.stream
先通過消費者訪問 http://192.168.0.1:8010/hystrix 再輸入 http://192.168.0.1:8020/turbine.stream

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