zoukankan      html  css  js  c++  java
  • 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)
            ......
    
  • 相关阅读:
    形象理解ERP(转)
    禁用windows server 2008 域密码复杂性要求策略
    How to adding find,filter,remove filter on display method Form
    Windows Server 2008 R2激活工具
    How to using bat command running VS development SSRS report
    Creating Your First Mac AppGetting Started
    Creating Your First Mac AppAdding a Track Object 添加一个 Track 对象
    Creating Your First Mac AppImplementing Action Methods 实现动作方法
    Creating Your First Mac AppReviewing the Code 审查代码
    Creating Your First Mac AppConfiguring the window 设置窗口
  • 原文地址:https://www.cnblogs.com/seve/p/11535891.html
Copyright © 2011-2022 走看看