SpringCloud學習筆記(4):Hystrix容錯機制


簡介

在微服務架構中,微服務之間的依賴關系錯綜復雜,難免的某些服務會出現故障,導致服務調用方出現遠程調度的線程阻塞。在高負載的場景下,如果不做任何處理,可能會引起級聯故障,導致服務調用方的資源耗盡甚至整個系統奔潰。Hystrix是一個由Netflix開源的一個延遲和容錯庫,它通過添加延遲容忍和容錯邏輯來幫助控制這些微服務之間的交互。Hystrix通過隔離服務之間的訪問點、停止跨服務的級聯故障並提供回退選項來實現這一點,所有這些選項都提高了系統的總體彈性。

項目介紹

  1. sc-parent,父模塊(請參照SpringCloud學習筆記(1):Eureka注冊中心)
  2. sc-eureka,注冊中心(請參照SpringCloud學習筆記(1):Eureka注冊中心)
  3. sc-provider,提供者(請參照SpringCloud學習筆記(1):Eureka注冊中心)
  4. sc-consumer-hystrix-ribbon,使用Hystrix+Ribbon的消費者
  5. sc-consumer-hystrix-feign,使用Hystrix+Feign的消費者

在Ribbon上使用Hystrix

1.在父模塊下創建子模塊項目sc-consumer-hystrix-ribbon,pom.xml:

<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>
  <parent>
    <groupId>com.cf</groupId>
    <artifactId>sc-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>sc-consumer-hystrix-ribbon</artifactId>
  
  <dependencies>
  	<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>
  </dependencies>
</project>

2.創建啟動類consumer.ConsumerApplication:

package consumer;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

@SpringBootApplication
@EnableCircuitBreaker
public class ConsumerApplication {

	public static void main(String[] args) {
		SpringApplication.run(ConsumerApplication.class, args);
	}
	
	//為RestTemplate整合Ribbon,使其具備負載均衡的能力
	@LoadBalanced
	@Bean
	public RestTemplate restTemplate(){
		return new RestTemplate();
	}
}

3.創建調用提供者服務的Controller:consumer.controller.ConsumerController

package consumer.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;

@RestController
public class ConsumerController {
	@Autowired
	private RestTemplate restTemplate;
	
	@HystrixCommand(fallbackMethod="getBookListFallBack")
	@GetMapping("/getBookList")
	public String getBookList(){
		return restTemplate.getForObject("http://sc-provider/book/list", String.class);
	}
	
	public String getBookListFallBack(){
		return "[\"Java入門到放棄\"]";
	}
}

@HystrixCommand:表示將getBookList方法作為hystrix命令調用的方法。
fallbackMethod:指定處理回退邏輯的方法,這里是getBookListFallBack方法,當getBookList方法跑出異常時將會調用getBookListFallBack方法。
注意:回退方法應該與作為hystrix命令調用的方法具有相同的簽名。

4.創建application.yml:

server:
  port: 8083

spring:
  application:
    name: sc-consumer-hystrix-ribbon
    
eureka:
  client:
    registerWithEureka: false
    serviceUrl:
      defaultZone: http://localhost:8080/eureka/    

5.測試

依次啟動注冊中心sc-eureka、提供者sc-provider、消費者sc-consumer-hystrix-ribbon,並訪問http://localhost:8083/getBookList,結果顯示如下:

這是提供者正常返回的值,接下來將提供者sc-provider關閉,再次訪問http://localhost:8083/getBookList,結果顯示如下:

因為將提供者sc-provider關閉后,消費者再訪問提供者時會報錯,Hystrix捕獲異常后會直接調用回退方法也就是getBookListFallBack方法。

在Feign上使用Hystrix

1.在父模塊下創建子模塊項目sc-consumer-hystrix-feign,pom.xml:

<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>
  <parent>
    <groupId>com.cf</groupId>
    <artifactId>sc-parent</artifactId>
    <version>0.0.1-SNAPSHOT</version>
  </parent>
  <artifactId>sc-consumer-hystrix-feign</artifactId>
  
  <dependencies>
  	<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>
  </dependencies>
</project>

2.創建啟動類feign.FeignApplication:

package feign;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
import org.springframework.cloud.openfeign.EnableFeignClients;

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

3.創建Feign聲明式接口:feign.inter.BookService

package feign.inter;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.PostMapping;

import feign.fallback.BookFallBack;

@FeignClient(value="sc-provider", fallbackFactory=BookFallBack.class)
public interface BookService {
	
	@GetMapping("/book/list")
	public String getBookList();
}

@FeignClient注解中的fallbackFactory屬性是指定的Feign客戶端界面定義回退工廠。

4.創建調用提供者服務的Controller:

package feign.controller;

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

import feign.inter.BookService;

@RequestMapping("/feign")
@RestController
public class FeignController {
	@Autowired
	private BookService bookService;
	
	@GetMapping("/getBookList")
	public String getBookList(){
		return bookService.getBookList();
	}
}

5.創建application.yml:

server:
  port: 8084

spring:
  application:
    name: sc-consumer-hystrix-feign

eureka:
  client:
    registerWithEureka: false
    serviceUrl:
      defaultZone: http://localhost:8080/eureka/   

feign:
  hystrix:
    enabled: true  #開啟hystrix支持     

6.創建回退工廠類:

package feign.fallback;
import org.springframework.stereotype.Component;

import feign.hystrix.FallbackFactory;
import feign.inter.BookService;

@Component
public class BookFallBack implements FallbackFactory<BookService>{
	@Override
	public BookService create(Throwable cause) {
		return new BookService() {
			@Override
			public String getBookList() {
				return "[\"Java入門到放棄\"]";
			}
		};
	}
}

create方法返回一個回退實例,回退實例為Feign聲明式接口BookService的實現類,提供了與BookService相對應的回退方法,BookService接口調用失敗時將會調用該實現類中的回退方法。

7.測試:

依次啟動注冊中心sc-eureka、提供者sc-provider、消費者sc-consumer-hystrix-feign,並訪問http://localhost:8084/feign/getBookList,結果顯示如下:

這是提供者正常返回的值,接下來將提供者sc-provider關閉,再次訪問http://localhost:8084/feign/getBookList,結果顯示如下:

8.查看回退原因

修改回退工廠類BookFallBack:

@Component
public class BookFallBack implements FallbackFactory<BookService>{
	@Override
	public BookService create(Throwable cause) {
		return new BookService() {
			@Override
			public String getBookList() {
				//將回退原因輸出到控制台
				cause.printStackTrace(System.out);
				return "[\"Java入門到放棄\"]";
			}
		};
	}
}

依次啟動注冊中心sc-eureka、消費者sc-consumer-hystrix-feign,並訪問http://localhost:8084/feign/getBookList,控制台輸出:

com.netflix.hystrix.exception.HystrixTimeoutException
	at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$1.run(AbstractCommand.java:1142)
	at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable$1.call(HystrixContextRunnable.java:41)
	at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable$1.call(HystrixContextRunnable.java:37)
	at com.netflix.hystrix.strategy.concurrency.HystrixContextRunnable.run(HystrixContextRunnable.java:57)
	at com.netflix.hystrix.AbstractCommand$HystrixObservableTimeoutOperator$2.tick(AbstractCommand.java:1159)
        ......


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM