spring cloud 入门系列四:使用Hystrix 实现断路器进行服务容错保护「建议收藏」

在微服务中,我们将系统拆分为很多个服务单元,各单元之间通过服务注册和订阅消费的方式进行相互依赖。但是如果有一些服务出现问题了会怎么样?比如说有三个服务(ABC),A调用B,B调用C。由于网络延迟或C

大家好,又见面了,我是全栈君。

在微服务中,我们将系统拆分为很多个服务单元,各单元之间通过服务注册和订阅消费的方式进行相互依赖。但是如果有一些服务出现问题了会怎么样?

比如说有三个服务(ABC),A调用B,B调用C。由于网络延迟或C本身代码有问题导致B迟迟得不到回应,这样B调用C的请求就会被挂起,等待。

在高并发的访问的情况下,这些挂起的线程得不到释放,使后续的请求阻塞,最终导致B也挂掉了。依次类推,A可能也会挂掉,进而使整个系统全部崩溃。

为了解决整个问题,Spring Cloud 使用Hystrix进行服务容错保护,包括断路器、线程隔离等一系列的保护功能,今天我们就来看下如何通过Hystrix实现断路器。

一、什么是Spring Cloud Hystrix?什么是断路器?

Spring Cloud Hystrix是基于Netflix的开源框架Hystrix实现的,其目的是为了通过控制那些访问远程系统、服务和第三方的节点,从而对延迟和故障提供强大的容错能力。

断路器类似于我们家里面强电箱里面用到的漏电断路保护器,当服务单元出现故障(类似于电器发生短路),通过断路器的故障监控功能(类似于保险丝),向调用方返回一个错误响应,避免长时间等待,从而避免故障蔓延到整个系统。

二、没有断路器的情况下,页面展示

还记得我们前面写的spring cloud 入门系列二:使用Eureka 进行服务治理里面的三个服务(eureka/hello-service/hello-consumer)吗?我们基于这个进行实验。

  1. 启动eureka服务注册中心,端口号1111
  2. 启动hello-service服务提供者,这里我们启动两个服务,端口号分别为9090,9091
  3. 启动hello-consumer服务消费者,端口号为9999;这个时候我们多次访问http://localhost:9999/hello-consumer是没有问题的
  4. 将hello-service端口号为9091的服务关掉,再去多次访问http://localhost:9999/hello-consumer,报错了spring cloud 入门系列四:使用Hystrix 实现断路器进行服务容错保护「建议收藏」

    PS:这里说明下,为什么要多次访问,是因为我们通过ribbon实现了负载均衡,访问http://localhost:9999/hello-consumer的时候,会轮询访问hello-service的两个服务,当访问到端口号是9091的服务时才报错,访问9090的服务就不会有问题。

三、断路器代码实现

接下来我们看下如何进行代码实现,我们不去修改服务注册中心和服务提供者,只需要修改服务消费者hello-consumer。

  1. 修改POM文件,引入Hystrix依赖
    <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.sam</groupId>
        <artifactId>hello-consumer</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.1.RELEASE</version>
        </parent>
    
        <properties>
            <javaVersion>1.8</javaVersion>
        </properties>
    
        <dependencyManagement>
            <dependencies>
                <dependency>
                    <groupId>org.springframework.cloud</groupId>
                    <artifactId>spring-cloud-dependencies</artifactId>
                    <version>Camden.SR6</version>
                    <type>pom</type>
                    <scope>import</scope>
                </dependency>
            </dependencies>
    
        </dependencyManagement>
    
        <dependencies>
            <!-- 引入eureka 客户端依赖 -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</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>
    
        </dependencies>
    </project>

  2. 修改启动类,追加注解@EnableCircuitBreaker,开启断路器
    @EnableDiscoveryClient
    @SpringBootApplication
    @EnableCircuitBreaker public class ConsumerApp {
    
    
        //@Bean 应用在方法上,用来将方法返回值设为为bean
        @Bean
        @LoadBalanced  //@LoadBalanced实现负载均衡
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
        
        public static void main(String[] args) {
            SpringApplication.run(ConsumerApp.class, args);
        }
    }

    这个时候你会发现,这个启动类加了三个注解,这个是不是很麻烦?没关系,我们可以使用注解@SpringCloudApplication

    @SpringCloudApplication public class ConsumerApp {
    
    
        //@Bean 应用在方法上,用来将方法返回值设为为bean
        @Bean
        @LoadBalanced  //@LoadBalanced实现负载均衡
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
        
        public static void main(String[] args) {
            SpringApplication.run(ConsumerApp.class, args);
        }
    }

    @SpringCloudApplication = @EnableDiscoveryClient +@SpringBootApplication+@EnableCircuitBreaker,从源码就能看出来:

    @Target(ElementType.TYPE)
    @Retention(RetentionPolicy.RUNTIME)
    @Documented
    @Inherited
    @SpringBootApplication @EnableDiscoveryClient @EnableCircuitBreaker public @interface SpringCloudApplication {
    }

  3. 追加service
    @Service
    public class ConsumerService {
        
        @Autowired
        RestTemplate restTemplate;
    
        @HystrixCommand(fallbackMethod = "errorMsg")
        public String consumer() {
            // 调用hello-service服务,注意这里用的是服务名,而不是具体的ip+port
            restTemplate.getForObject("http://hello-service/hello", String.class);
            return "hello consumer finish !!!";
        }
    
        public String errorMsg() {
            return "error!!!";
        }
    }

    我们把原来controller里面的调用RestTemplate的实现放到service里面,并且通过@HystrixCommand来指定回调方法,当出现错误时调用该方法。

  4. 修改controller
    /**
     *这里不再直接调用restTemplate,
     *而是通过调用service进行实现 
     *
     */
    @RestController
    public class ConsumerController {
    
        @Autowired
    //    RestTemplate restTemplate;
        ConsumerService service;
        
        
        @RequestMapping("/hello-consumer")
        public String helloConsumer() {
    //        //调用hello-service服务,注意这里用的是服务名,而不是具体的ip+port
    //        restTemplate.getForObject("http://hello-service/hello", String.class);
            return service.consumer();
        }
    }

  5. 测试,多次访问,当报错的时候,会显示如下内容

    spring cloud 入门系列四:使用Hystrix 实现断路器进行服务容错保护「建议收藏」

     

大功告成!

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/120907.html原文链接:https://javaforall.net

赞 (0)
全栈程序员-站长的头像全栈程序员-站长

相关推荐

  • apache 负载均衡 超时设置_apache负载均衡配置

    apache 负载均衡 超时设置_apache负载均衡配置最近因为新疆移动项目的要求,必须要用负载均衡来实现HTTP请求,没办法,我这个人一般是有压力的环境下才会好好学习,所以只有老实的自己来边学边写了。   其实,我们在平时经常听说集群这个名词,但是真正知道的又有几个呢,恩,好了,不讲废话了,我就先给大家扫盲吧,当然,我讲的不一定是对的,我就把我自己知道的讲出来,集群目前分3类吧,科学集群、高可用性集群、负载均衡集群。    科学集群(ScientificClustering,简称SC):使用特殊的软硬件技术将大量的计算能力有限的机器连接成计算能力巨大

    2022年9月4日
  • Django(50)drf异常模块源码分析

    Django(50)drf异常模块源码分析异常模块源码入口APIView类中dispatch方法中的:response=self.handle_exception(exc)源码分析我们点击handle_exception跳转,查看该

    2022年8月7日
  • java 异常分类和处理机制

    java 异常分类和处理机制一、背景介绍程序在运行过程中发生错误或异常情况是不可避免的,如果每一个运行时错误都由程序员手动控制和处理,其工作量是不可想象的。Java语言中的异常处理机制就解决的上述问题,把错误与异常的管理带到了面向对象的世界Java语言定义了很多异常类,将运行错误和异常的信息和处理方法封装在了异常类中,帮助程序员检查和控制异常。即J…

    2022年5月13日
  • git 比较两个分支不同的commit[通俗易懂]

    git 比较两个分支不同的commit

    2022年2月9日
  • Latex 安装及学习教程「建议收藏」

    Latex 安装及学习教程「建议收藏」Latex下载安装及使用教程一介绍(一)关于LaTeX和CTeX二TexLive2018+WinEdt10.3安装(一)基本安装(二)使用介绍(三)完整的入门资源:一介绍(一)关于LaTeX和CTeXLatex是一种排版系统。TeX是LaTeX的基石,LaTeX建立在TeX之上。但是,与Word相比,LaTeX显得不那么友好,于是主要从安装开始给大家介绍一下。希…

    2022年4月30日
  • LMDB笔记_pdf怎么做笔记

    LMDB笔记_pdf怎么做笔记作为一个计算机底层小白,在了解一个知识点的时候时常需要恶补很多基础知识。本文记录在了解LMDB过程中接触的知识点。LMDB基本架构一个比较官方的解释:lmdb的基本做法是使用mmap文件映射,不管这个文件存储实在内存上还是在持久存储上。lmdb的所有读取操作都是通过mmap将要访问的文件只读的映射到虚拟内存中,直接访问相应的地址.因为使用了read-only的mmap,同样避免了程序错误将存…

    2022年9月29日

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号