• Spring Cloud Hystrix 服务容错保护 5.1


    Spring Cloud Hystrix介绍

      在微服务架构中,通常会存在多个服务层调用的情况,如果基础服务出现故障可能会发生级联传递,导致整个服务链上的服务不可用
    为了解决服务级联失败这种问题,在分布式架构中产生了断路器等一系列的服务保护机制。分布式架构中的断路器,有些类似于我们生活中的空气开关,当电路发生短路等情况时,空气开关会立刻断开电流,以防止用电火灾的发生。
      在Spring Cloud中,Spring Cloud Hystrix就是用来实现断路器、线程隔离等服务保护功能的。Spring Cloud Hystrix是基于Netflix的开源框架Hystrix实现的,该框架的使用目标在于通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。
    与空气开关不能自动重新打开有所不同的是,断路器是可以实现弹性容错的,在一定条件下它能够自动打开和关闭,其使用时主要有三种状态,如图5-2所示。

      在图5-2中,断路器的开关由关闭到打开的状态是通过当前服务健康状况(服务的健康状况=请求失败数/请求总数)和设定阈值(默认为10秒内的20次故障)比较决定的。当断路器开关关闭时,请求被允许通过断路器,如果当前健康状况高于设定阈值,开关继续保持关闭;如果当前健康状况低于设定阈值,开关则切换为打开状态。当断路器开关打开时,请求被禁止通过;如果设置了fallback方法,则会进入fallback的流程。当断路器开关处于打开状态,经过一段时间后,断路器会自动进入半开状态,这时断路器只允许一个请求通过;当该请求调用成功时,断路器恢复到关闭状态;若该请求失败,断路器继续保持打开状态,接下来的请求会被禁止通过。
      Spring Cloud Hystrix能保证服务调用者在调用异常服务时快速地返回结果,避免大量的同步等待,这是通过HystrixCommand的fallback方法实现的
      但采用fallback的方式可以给用户一个友好的提示结果,这样就避免了其他服务的崩溃问题。

    Spring Cloud Hystrix的使用

      了解了为什么需要使用Hystrix,以及Hystrix在使用时的三种状态后,下面通过一个案例来讲解如何在应用中使用SpringCloud Hystrix来实现断路器的容错功能,并使用FallBack()方法为熔断或异常提供备选方案。案例中主要涉及到以下几个工程:
      ·xcservice-eureka-server工程:服务注册中心,端口为8761;
      ·xcservice-eureka-order工程:服务提供者,需要启动两个订单实例,其端口号分别为7900和7901;
      ·xcservice-eureka-user-hystrix工程:服务消费者,使用Ribbon实现的,端口号为8030,此工程可以在xcservice-eu-reka-user工程内容的基础上修改。
      在上述三个工程中,xcservice-eureka-server和xcservice-eureka-order可以使用第4章中所创建的工程,而xcservice-eureka-user-hystrix工程需要重新搭建和编写。其具体实现过程如下。
      (1)创建xcservice-eureka-user-hystrix工程,并在其pom.xml中引入eureka和hystrix的依赖,如文件5-1所示。
      文件5-1 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>
        <parent>
            <groupId>com.xc</groupId>
            <artifactId>xcservice-springcloud</artifactId>
            <version>0.0.1-SNAPSHOT</version>
        </parent>
        <groupId>com.xc</groupId>
        <artifactId>xcservice-eureka-user-hystrix</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <name>xcservice-eureka-user-hystrix</name>
        <description>服务消费者</description>
    
        <properties>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
            </dependency>
    
            <dependency><!-- Hystrix依赖 -->
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-hystrix</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-test</artifactId>
                <scope>test</scope>
            </dependency>
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>

      (2)编辑配置文件。在配置文件中添加Eureka服务实例的端口号、服务端地址等,如文件5-2所示。
      文件5-2 application.yml

    server:
      port: 8030 # 指定该Eureka实例的端口号
    
    eureka:
      instance:
        prefer-ip-address: true  # 是否显示主机的IP
        #instance-id: ${spring.cloud.client.ipAddress}:${server.port} #将Status中的显示内容也以“IP:端口号”的形式显示
      client:
        service-url:
          defaultZone: http://localhost:8761/eureka/ # 指定Eureka服务端地址
    
    spring:
      application:
        name: xcservice-eureka-user-hystrix # 指定应用名称

      (3)在工程主类Application中使用@EnableCircuitBreaker注解开启断路器功能,编辑后如文件5-3所示。
      文件5-3 Application.java

    package com.xc.xcserviceeurekauserhystrix;
    
    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.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.context.annotation.Bean;
    import org.springframework.web.client.RestTemplate;
    
    @SpringBootApplication
    @EnableCircuitBreaker
    @EnableEurekaClient
    public class XcserviceEurekaUserHystrixApplication {
    
        /**
         * 实例化RestTemplate
         * RestTemplate是Spring提供的用于访问Rest服务的客户端,
         * 它提供了多种便捷访问远程Http服务的方法,能够大大提高客户端的编写效率。
         */
        @Bean
        @LoadBalanced
        public RestTemplate restTemplate() {
            return new RestTemplate();
        }
    
        public static void main(String[] args) {
            SpringApplication.run(XcserviceEurekaUserHystrixApplication.class, args);
        }
    
    }

      (4)修改用户控制器类。在findOrdersByUser()方法上添加@HystrixCommand注解来指定回调方法,编辑后如文件5-4所示。
      文件5-4 UserController.java

    package com.xc.xcserviceeurekauserhystrix.controller;
    
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    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 org.springframework.web.client.RestTemplate;
    
    @RestController
    public class UserController {
    
        @Autowired
        private RestTemplate restTemplate;
    
        /**
         * http://localhost:8030/findOrdersByUser/1
         * 查找与用户相关的订单
         */
        @GetMapping("/findOrdersByUser/{id}")
        @HystrixCommand(fallbackMethod = "fallbackInfo")
        public String findOrdersByUser(@PathVariable String id) {
            // 假设用户只有一个订单,并且订单id为123
            // int oid = 123;
            // return restTemplate.getForObject("http://localhost:7900/order/" + oid, String.class);
            return restTemplate.getForObject("http://xcservice-eureka-order/order/" + id, String.class);
        }
    
        /**
         * 返回信息方法
         */
        public String fallbackInfo(@PathVariable String id) {
            return "服务不可用,请稍后再试!";
        }
    
    }

      在上述代码中,@HystrixCommand注解用于指定当前方法发生异常时调用的方法,该方法是通过其属性fallbackMethod的属性值来指定的。这里需要注意的是,回调方法的参数类型以及返回值必须要和原方法保持一致。

      (5)分别启动注册中心、服务提供者(7900和7901)和服务消费者。
      当多次访问http://localhost:8030/findOrdersByUser/1时,后台将通过轮询的方式分别访问7900和7901端口所对应的服务。此时如果停止7901对应的服务,那么多次执行访问时,在轮询到7901端口对应的服务时,页面将显示提示信息(服务不可用,请稍后再试!),这也就说明Spring Cloud Hystrix的服务回调(fallbackInfo()方法)生效。

  • 相关阅读:
    无线电频谱和波段划分
    数字IC设计工程师推荐用书
    Verilog HDL 经典用书
    Interfacing Two Clock Domains
    值得借鉴的Perl学习总结
    MIMO技术原理、概念、现状简介
    cs0016:未能写入输出文件 "c:"WINDOWS"Microsoft.NET"Framework"v2.0.50727"Temporary ASP.NET Files"root"...."*.dll“拒绝访问”
    Sql Server 2005 数据库备份还原后出现“受限制用户”问题的解决
    两个路由器连接的连接方法
    2个表之间复制数据
  • 原文地址:https://www.cnblogs.com/ooo0/p/11191368.html
Copyright © 2020-2023  润新知