zoukankan      html  css  js  c++  java
  • SpringCloud-day08-Hystrix断路器

    8.Hystrix断路器

    8.1.Hystrix简介

    在分布式系统中往往存在着大量的服务依赖关系,其中不可避免的会出现部分服务因为发生故障而无法正常提供服务。

    这时候调用方如果没有对被依赖服务的故障进行有效的隔离,那么可能将当前服务所在容器的资源消耗殆尽,进而引发上一级的服务出现问题,最后有可能导致整个系统发生雪崩效应。

    为了应对这种情况,我们需要对依赖服务进行降级处理,同时对被依赖服务故障进行隔离。

    Hystrix是Netflix开源的服务故障隔离、恢复、监控和报警的组件。Hystrix通过添加对被依赖服务延迟和故障处理逻辑控制服务间的交互,进而提高整个系统的稳定性。

    hystrix对应的中文名字是“豪猪”,豪猪周身长满了刺,能保护自己不受天敌的伤害,代表了一种防御机制,这与hystrix本身的功能不谋而合,因此Netflix团队将该框架命名为Hystrix,并使用了对应的卡通形象做作为logo。

    8.2.服务雪崩效应 

      当一个请求依赖多个服务的时候:

      正常情况下的访问 :

      

      但是,当请求的服务中出现无法访问、异常、超时等问题时(图中的I),那么用户的请求将会被阻塞。

      

      如果多个用户的请求中,都存在无法访问的服务,那么他们都将陷入阻塞的状态中。

      

      Hystrix的引入,可以通过服务熔断和服务降级来解决这个问题。

    8.3.Hystrix服务熔断服务降级 

      Hystrix服务熔断服务降级具体实现 @HystrixCommand fallbackMethod

      熔断机制是应对雪崩效应的一种微服务链路保护机制。

      当某个服务不可用或者响应时间超时,会进行服务降级,进而熔断该节点的服务调用,快速返回自定义的错误影响页面信息。

    8.4.实际应用

    第一步:单独编写一个服务提供者,我们以提共一个锁票服务为例

      构建模块:ticket-lock-provider-6004

      注意:本质上是拷贝一个服务提供者(如:6001),在上面添加Hystrix的配置即可。

      项目结构如下:

      

    第二步: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">
        <parent>
            <artifactId>wfd360-station</artifactId>
            <groupId>com.wfd360.station</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>ticket-lock-provider-6004</artifactId>
        <dependencies>
            <dependency>
                <groupId>com.wfd360.station</groupId>
                <artifactId>common</artifactId>
                <version>${project.version}</version>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-data-jpa</artifactId>
            </dependency>
            <dependency>
                <groupId>mysql</groupId>
                <artifactId>mysql-connector-java</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-tomcat</artifactId>
            </dependency>
            <dependency>
                <groupId>com.alibaba</groupId>
                <artifactId>druid</artifactId>
            </dependency>
            <!--  eureka 依赖-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-eureka</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-config</artifactId>
            </dependency>
            <!-- actuator监控引入 -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
            <!-- 服务熔断降级-hystrix-->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-hystrix</artifactId>
            </dependency>
            <!-- 修改后立即生效,热部署 -->
            <dependency>
                <groupId>org.springframework</groupId>
                <artifactId>springloaded</artifactId>
            </dependency>
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-devtools</artifactId>
            </dependency>
        </dependencies>
    
    </project>
    View Code

    第二步:application.yml文件

    server:
      port: 6004
      context-path: /
    
    # 数据源配置
    spring:
      application:
        name: service-lock
      datasource:
        type: com.alibaba.druid.pool.DruidDataSource
        driver-class-name: com.mysql.jdbc.Driver
        url: jdbc:mysql://localhost:3306/db_station
        username: root
        password: admin
      jpa:
        hibernate:
          ddl-auto: update
        show-sql: true
      thymeleaf:
        cache: false
    
    # eureka 注册中心配置
    eureka:
      instance:
        hostname: localhost #eureka客户端主机实例名称
        appname: service-lock #客户端服务名称(可以随意取)
        instance-id: service-lock:6004 #客户端实例名称(可以随意取)
        prefer-ip-address: true #显示ip地址
      client:
        service-url:
          #defaultZone: http://localhost:7001/eureka #eureka的服务器地址(单机)
          defaultZone: http://eureka7001.wfd360.com:7001/eureka/,http://eureka7002.wfd360.com:7002/eureka/,http://eureka7003.wfd360.com:7003/eureka/ # 集群
    
    # 设置超时时间为2秒,如果不配置默认是1秒
    hystrix:
      command:
        default:
          execution:
            isolation:
              thread:
                timeoutInMilliseconds: 2000
    
    # 服务提供者信息
    info:
      version: v2
      WeChat: 851298348
      负责人: 姿势帝
    View Code

    这里注意3点:

    1.端口号为:6004

    2.服务名称为:service-lock,这个名称在消费端会使用

    3.设置服务超时时间为:2秒,如果不设置默认为1秒

    第三步:编写启动类:TicketProviderApplication_6004

    package com.wfd360;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.client.circuitbreaker.EnableCircuitBreaker;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    
    /**
     * Created by 姿势帝-博客园 on 2020/6/25.
     * 欢迎添加笔者wx(851298348)共同探讨、学习!
     */
    @SpringBootApplication
    @EnableEurekaClient
    // 开启断路器
    @EnableCircuitBreaker
    public class TicketProviderApplication_6004 {
        /**
         * @param args
         */
        public static void main(String[] args) {
            SpringApplication.run(TicketProviderApplication_6004.class, args);
        }
    }
    View Code

    这里注意:相比之前的服务提供者,这里增加了一个服务熔断的注解: @EnableCircuitBreaker

    第四步:编写控制层,lockTicket 锁票方法,以及服务熔断时的方法 lockTicketFallback

    package com.wfd360.controller;
    
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.ResponseBody;
    
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * Created by 姿势帝-博客园 on 2020/3/25.
     * 欢迎添加笔者wx(851298348)共同探讨、学习!
     */
    @Controller
    public class TicketController {
    
        /**
         * 锁票业务
         *
         * @return
         * @throws InterruptedException lockTicketFallback 回调函数名称
         */
        @ResponseBody
        @GetMapping(value = "/lock/ticket/{id}")
        @HystrixCommand(fallbackMethod = "lockTicketFallback")
        public Map<String, Object> lockTicket(@PathVariable("id") Integer id) throws InterruptedException {
            // 模拟锁票业务耗时
            // 便于测试-动态控制睡眠时间,这里使用id的值作为睡眠时长
            Thread.sleep(id);
            Map<String, Object> map = new HashMap<>();
            map.put("code", 200);
            map.put("msg", "操作成功");
            map.put("data", "锁定车票id=" + id);
            return map;
        }
    
        /**
         * 模拟锁票超时 或者 系统故障的回调函数
         *
         * @return
         * @throws InterruptedException
         */
        public Map<String, Object> lockTicketFallback(Integer id) {
            System.out.println("=========error110========");
            Map<String, Object> map = new HashMap<>();
            map.put("code", 900);
            map.put("msg", "系统出错,稍后重试,id=" + id);
            return map;
        }
    }
    View Code

    第五步:测试6004服务是否可用

    启动服务提供者:6004

    访问:http://localhost:6004/lock/ticket/10

    这里注意:在程序设计时,我们将id作为了睡眠时长可用同过传入不同大小的id模拟测试请求超时的情况

    测试结果如下:

    正常情况:

     模拟超时的情况:

    第六步:在消费者 service-ticket-consumer-80 模块中添加一个消费售票的消费

    package com.wfd360.controller;
    
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import org.springframework.web.client.RestTemplate;
    
    import java.util.Map;
    
    /**
     * @author 姿势帝-博客园
     * @address https://www.cnblogs.com/newAndHui/
     * @WeChat 851298348
     * @create 06/29 10:25
     * @description
     */
    @Controller
    @RequestMapping("/lock")
    public class TicketLockConsumerController {
        @Autowired
        private RestTemplate restTemplate;
        /**
         * 加入Eureka注册中心和ribbon后的使用
         */
        private static final String URL = "http://SERVICE-LOCK/";
    
    
        /**
         * 查询车票信息
         *
         * @return
         */
        @SuppressWarnings("unchecked")
        @GetMapping(value = "/ticket/{id}")
        @ResponseBody
        public Map<String, Object> lockTicket(@PathVariable("id") Integer id) {
            return restTemplate.getForObject(URL + "/lock/ticket/" + id, Map.class);
        }
        
    }
    View Code

    第七步:测试

    先启动eureka,在启动6004服务提供者,80服务消费者;

    通过传入不同的id,进而不同的睡眠时间,观察测试结果,同时测试是也可以修改配置的超时时间观察结果

    浏览器:http://localhost/lock/ticket/10

    模拟正常情况:

     模拟超时情况:

    通过上述测试,可以判定hystrix起到了服务降级熔断的作用,

    springCloud课程与代码下载:https://www.cnblogs.com/newAndHui/p/13210228.html

    完美!

  • 相关阅读:
    Java编程技术之浅析SPI服务发现机制
    Java编程开发之浅析Java引用机制
    xmake v2.5.5 发布,支持下载集成二进制镜像包
    C/C++ 构建系统,我用 xmake
    xmake v2.5.3 发布,支持构建 linux bpf 程序和 Conda 包集成
    xmake v2.5.2 发布, 支持自动拉取交叉工具链和依赖包集成
    程序员是怎么存档并管理文件版本的?
    《大厂程序员春招实习面试漫画》第一集:基础面试
    漫画解释啥是云计算
    程序员,这个需求你是真实现不了吗?
  • 原文地址:https://www.cnblogs.com/newAndHui/p/10635308.html
Copyright © 2011-2022 走看看