• SpringCloud中的Hystrix概述


    服务雪崩

    多个微服务之间调用的时候,A调用微服务B和微服务C,微服务B和微服务C调用了其他的微服务,这就是所谓的“扇出”。如果扇出的链路上某个微服务的调用响应的时间过长或者不可用,对微服务A的调用会占用越来越多的系统资源,进而引起系统崩溃,所谓的“雪崩效应”。

    什么是Hystrix?

    Hystrix是一个用于处理分布式系统的延迟和容错的开源库,在分布式系统里,许多毅力啊不可避免的会调用失败,比如超时、异常等,Hystrix能够保障在一个依赖出问题的情况下,不会导致整体服务失败,避免级联故障,以提高分布式系统的弹性

    Hystrix可以用来干嘛?

    • 服务降级
    • 依赖隔离
    • 服务熔断

    官网地址:https://github.com/Netflix/Hystrix/wiki/How-To-Use

    什么是服务降级?

    降级机制时应对雪崩效应的一种微服务链路保护机制

    当链路的某个微服务不可用或者响应时间太长,会进行服务的降级,进而降级微服务的调用,快速返回“错误”的信息。

    优先核心服务,非核心服务不可用或者弱化

    通过HystrixCommand注解指定

    FallbackMethod(回退函数)中具体实现降级逻辑

    • 案例:在pom文件中导入坐标
       1  <dependencies>
       2         <dependency>
       3             <groupId>junit</groupId>
       4             <artifactId>junit</artifactId>
       5         </dependency>
       6         <dependency>
       7             <groupId>mysql</groupId>
       8             <artifactId>mysql-connector-java</artifactId>
       9         </dependency>
      10         <dependency>
      11             <groupId>com.alibaba</groupId>
      12             <artifactId>druid</artifactId>
      13         </dependency>
      14         <dependency>
      15             <groupId>ch.qos.logback</groupId>
      16             <artifactId>logback-core</artifactId>
      17         </dependency>
      18         <dependency>
      19             <groupId>org.mybatis.spring.boot</groupId>
      20             <artifactId>mybatis-spring-boot-starter</artifactId>
      21         </dependency>
      22 
      23         <dependency>
      24             <groupId>org.springframework.boot</groupId>
      25             <artifactId>spring-boot-starter-web</artifactId>
      26         </dependency>
      27         <dependency>
      28             <groupId>org.springframework.boot</groupId>
      29             <artifactId>spring-boot-starter-test</artifactId>
      30         </dependency>
      31 
      32         <!-- 修改后立即生效,热部署 -->
      33         <!-- https://mvnrepository.com/artifact/org.springframework/springloaded -->
      34         <dependency>
      35             <groupId>org.springframework</groupId>
      36             <artifactId>springloaded</artifactId>
      37             <version>1.2.8.RELEASE</version>
      38         </dependency>
      39 
      40         <dependency>
      41             <groupId>org.springframework.boot</groupId>
      42             <artifactId>spring-boot-devtools</artifactId>
      43         </dependency>
      44         <dependency>
      45             <groupId>zh.stu.springcloud</groupId>
      46             <artifactId>zhservicecloud-common</artifactId>
      47             <version>1.0-SNAPSHOT</version>
      48         </dependency>
      49         <!--将微服务provider注册到eureka-->
      50         <dependency>
      51             <groupId>org.springframework.cloud</groupId>
      52             <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
      53         </dependency>
      54         <dependency>
      55             <groupId>org.springframework.cloud</groupId>
      56             <artifactId>spring-cloud-starter-config</artifactId>
      57         </dependency>
      58         <!--监控完善信息-->
      59         <dependency>
      60             <groupId>org.springframework.boot</groupId>
      61             <artifactId>spring-boot-starter-actuator</artifactId>
      62         </dependency>
      63         <dependency>
      64             <groupId>org.springframework.cloud</groupId>
      65             <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
      66         </dependency>67 
      68     </dependencies>
    • 在yml的文件中添加配置                      
       1 server:
       2   port: 8001
       3 mybatis:
       4   config-location: classpath:mybatis/mybatis.cfg.xml    #mybatis配置文件所在路径
       5   type-aliases-package: com.zjx.springcloud.entity      #所有Entity别名类所在包
       6   mapper-locations:
       7    - classpath:mybatis/mapper/**/*.xml                   #mapper映射文件
       8 spring:
       9   application:
      10     name: txservicecloud-dep
      11   datasource:
      12     type: com.alibaba.druid.pool.DruidDataSource        #当前数据源操作类型
      13     driver-class-name: org.gjt.mm.mysql.Driver          #mysql驱动包
      14     url: jdbc:mysql://localhost:3306/cloudDB01          #数据库名称
      15     username: root
      16     password: root
      17     dbcp2:
      18       min-idle: 5                                       #数据库连接池的最小维持连接数
      19       initial-size: 5                                   #初始化连接数
      20       max-total: 5                                      #最大连接数
      21       max-wait-millis: 200                              #等待连接获取的最大超时时间
      22 
      23 eureka:
      24   client: #客户端注册进eureka服务列表内
      25     service-url:
      26       defaultZone: http://eureka7001.com:7001/eureka/,http://eureka7002.com:7002/eureka/,http://eureka7003.com:7003/eureka/
      27       #defaultZone: http://localhost:7001/eureka
      28   instance:
      29     instance-id: txservicecloud-dep-hystrix-8001  #这个就是我用来做测试的模块的名字
      30     prefer-ip-address: true
      31 info:
      32   app.name: txservicecloud-dep
      33   company.name: www.txjava.cn
      34   build.artifactId: @project.artifactId@
      35   build.version: @project.version@
    • 可以编写一个查询数据库的一个案例,分不同的层,dao层,service....以及实现接口和xml文件。此处省略。直接在控制器中去模拟场景
    • 例如在DeptController中模拟超时异常
       1    /**
       2      * @HystrixCommand  在注解中有一个
       3      * fallbackMethod  :在这个调用这个方法发生错误的时候会出发fallbackMethod中的方法,达到一个降级的效果。
       4      *
       5      *
       6      * commandProperties : 是一个数组的形式,比如在里面可以配置超时的属性
       7      * 里面的name的属性,可以在HysrixConmmandProperties.class文件中查找
       8      * @param id
       9      * @return
      10      */
      11 
      12     @HystrixCommand(fallbackMethod = "HystrixProcess",
      13     commandProperties = {
      14             @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1000")
      15     })
      16     @RequestMapping(value = "/dept/get/{id}",method = RequestMethod.GET)
      17     public Dept dept (@PathVariable("id") Long id){
      18         try {
      19 //            这个方法表示,在线程休眠时间大于一秒的时候,该方法上的注解:@HystrixCommand会调用方法HystrixProcess中的提示信息。
      20             Thread.sleep(2000);
      21         } catch (InterruptedException e) {
      22             e.printStackTrace();
      23         }
      24         return deptService.findById(id);
      25     }

      因为在注解@HystrixCommand(fallbackMethod = "HystrixProcess",中调用HystrixProcess的方法,所以在添加一个HystrixProcess的方法。

       1 /**
       2      * 降级的服务的方法和返回值要和服务方法的方法一致
       3      * @param id
       4      * @return
       5      */
       6     public Dept HystrixProcess(@PathVariable("id") Long id){
       7         Dept dept=new Dept();
       8         dept.setDeptno(id);
       9         dept.setDname("该ID"+id+"没有对应的信息,null--@HystrixCommand");
      10         dept.setDb_source("访问超时");
      11         return dept;
      12 
      13     }

      这样在方法  dept   的这个方法的时候就会进入到   HystrixProcess   的这个方法中,提示异常的信息。

    • 服务的超时我们也可以使用配置的方式来使用,在服务端的yml文件中

      1 hystrix:
      2   command:
      3     default:
      4        execution:
      5           isolation:
      6             thread :
      7               timeoutInMilliseconds: 1000

    注意:服务的降级方法的返回值和参数要和服务接口方法一致,默认降级方法可以设置参数列表为空。

    @DefaultProperties(defaultFallback = "hystrixFallBack")可以通过@DefaultProperties来指定一个默认的服务降级方法,如果方法返回值统一(本例子统一了返回值的接口为String,默认的回退方法没有参数)则可以给多个服务接口来做服务降级。服务端的接口返回值修改,注意:服务消费端返回值也要修改成String。

    服务熔断

    什么是服务熔断?

    当链路的某个微服务不可用或者响应时间太长,会进行服务的降级,进而熔断微服务的调用,快速返回"错误"的响应信息.当检测到该节点微服务调用响应正常后恢复调用链路.在SpringCloud框架里熔断机制通过Hystrix实现.Hystrix会监控微服务调用的状况,当失败的调用到一定阈值,缺省是5秒内20次调用失败就会启动熔断机制.熔断机制的注解是@HystrixCommand.

    正常状态下,熔断器是关闭的一个状态,当出现调用失败、网络超时等就会处于打开的一种状态,当网络恢复之后就会处于半打开的一种状态。

      

      

    circuitBreaker.enabled

    熔断开启

    circuitBreaker.requestVolumeThreshold

    此属性设置时间窗口中请求断路的最小请求数。

    例如,如果该值为20,那么如果在时间窗中仅接收19个请求(例如,10秒的时间窗),即使所有19个电路都失败,电路也不会跳闸。

    circuitBreaker.sleepWindowInMilliseconds

    熔断后的重试时间窗口,且在该时间窗口内只允许一次重试。即在熔断开关打开后,在该时间窗口允许有一次重试,如果重试成功,则将重置Health采样统计并闭合熔断开关实现快速恢复,否则熔断开关还是打开状态,执行快速失败。

    circuitBreaker.errorThresholdPercentage

    如果在一个采样时间窗口内,失败率超过该配置,则自动打开熔断开关实现降级处理,即快速失败。默认配置下采样周期为10s,失败率为50%。

    在controller中访问方法是dept其中num的参数是2的就会在浏览器中提示服务器开小差的提示

        @Autowired
        private DeptService deptService;
    
    
        @HystrixCommand(fallbackMethod = "getfallback"
                ,commandProperties = {
                @HystrixProperty(name = "circuitBreaker.enabled", value = "true"),
                @HystrixProperty(name = "circuitBreaker.requestVolumeThreshold", value = "10"),
                @HystrixProperty(name = "circuitBreaker.sleepWindowInMilliseconds", value = "10000"),
                @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage", value = "60")
        })
        @RequestMapping(value = "/dept/get/{id}/{num}",method = RequestMethod.GET)
        public Dept dept (@PathVariable("id") Long id,@PathVariable("num") int num){
            if(num==2){
                try {
                    Thread.sleep(2000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            return deptService.findById(id);
        }
    
    
        /**
         * 降级的服务的方法和返回值要和服务方法的方法一致
         * @param id
         * @return
         */
        public Dept HystrixProcess(@PathVariable("id") Long id,@PathVariable("num") int num){
            Dept dept=new Dept();
            dept.setDeptno(id);
            dept.setDname("服务开小差");
            dept.setDb_source("服务开小差");
            return dept;
        }

    Feign中的Hystrix中的两种降级方式

    第一种:

    采用在接口调用服务的方式来做服务的熔断。

    • 在子类的工程中的公共模块中添加一个接口
       1 /**
       2  * DeptClientServiceFallbackFactory:实现该接口的类
       3  */
       4 @FeignClient(value = "zhservicecloud-dept",fallbackFactory = DeptClientServiceFallbackFactory.class)
       5 public interface DeptClientService {
       6 
       7 
       8     @RequestMapping(value = "/dept/add",method = RequestMethod.POST)
       9     public boolean add(@RequestBody Dept dept);
      10 
      11     @RequestMapping(value = "/dept/get/{id}",method = RequestMethod.GET)
      12     public Dept getdept (@PathVariable("id") Long id);
      13 
      14     @RequestMapping(value = "/dept/list",method = RequestMethod.GET)
      15     public List<Dept> findAlldept();
      16 
      17 }

      比如我是在对数据做的一系列操作模拟异常

    • 在子类的工程中的公共模块中添加的一个类
       1 /**
       2  * 实现接口:FallbackFactory
       3  *
       4  * DeptClientService接口
       5  */
       6 @Component
       7 public class DeptClientServiceFallbackFactory implements FallbackFactory<DeptClientService> {
       8     @Override
       9     public DeptClientService create(Throwable throwable) {
      10         return new DeptClientService() {
      11             @Override
      12             public boolean add(Dept dept) {
      13                 return false;
      14             }
      15 
      16             @Override
      17             public Dept getdept(Long id) {
      18                 return null;
      19             }
      20 
      21             @Override
      22             public List<Dept> findAlldept() {
      23                 System.out.println("Feign的第一种降级方式");
      24                 return null;
      25             }
      26         };
      27     }
      28 }
    • 在模块Feign的消费端的yml文件中追加配置
      1 feign:
      2   hystrix:
      3     enabled: true

      注意:这是在服务的消费端,如果想要设置熔断的其他都需要在服务的消费端设置

    • 在提供端的Controller中做测试
       1     @RequestMapping(value = "/dept/list",method = RequestMethod.GET)
       2     public List<Dept> dept()
       3     {
       4         try {
       5             Thread.sleep(2000);
       6         } catch (InterruptedException e) {
       7             e.printStackTrace();
       8         }
       9         return deptService.findAll();
      10     }

    Feign的第二种降级方式

    • 同样是在子模块下的common模块下新建一个接口
       1 @FeignClient(value = "zhservicecloud-dept",fallbackFactory = DeptClientService1.DeptClientFallBack.class)
       2 public interface DeptClientService1 {
       3 
       4     @RequestMapping(value = "/dept/add",method = RequestMethod.POST)
       5     public boolean add(@RequestBody Dept dept);
       6 
       7     @RequestMapping(value = "/dept/get/{id}",method = RequestMethod.GET)
       8     public Dept getdept(@PathVariable("id") Long id);
       9 
      10     @RequestMapping(value = "/dept/list",method = RequestMethod.GET)
      11     public List<Dept> findAlldept();
      12 
      13 //    创建一个内部类
      14     @Component
      15     static class DeptClientFallBack implements DeptClientService1{
      16 
      17         @Override
      18         public boolean add(Dept dept) {
      19             return false;
      20         }
      21 
      22         @Override
      23         public Dept getdept(Long id) {
      24             return null;
      25         }
      26 
      27         @Override
      28         public List<Dept> findAlldept() {
      29             System.out.println("Feign第二种降级方式");
      30             return null;
      31         }
      32     }
      33 
      34 }
    • 在Feign的消费端中的Controller测试
       1 @RestController
       2 public class DeptController1 {
       3 
       4 
       5     @Autowired
       6     private DeptClientService1 deptClientService;
       7 
       8     @RequestMapping("/consumer1/dept/getdept/{id}")
       9     public Dept getDept(@PathVariable("id") Long id){
      10         return deptClientService.getdept(id);
      11     }
      12 
      13     @RequestMapping("/consumer1/dept/findall")
      14     public List<Dept> findAll(){
      15         return deptClientService.findAlldept();
      16     }
      17 }
  • 相关阅读:
    您知道SASS吗?
    打破技术壁垒, 用SpreadJS 抢占“表格文档协同编辑系统”的入市先机
    7种你应该知道的JavaScript常见的错误
    前端开发:这10个Chrome扩展你不得不知
    疫情下,买菜难,其实卖菜的也是这么想的
    疫情之下远程办公,开启企业办公的全新时代!
    “泛在电力物联网”究竟是什么?
    2020 春节集五福最详细收集攻略
    怎样使我们的用户不再抵触填写Form表单?
    新事业,新征程:换屏哥,您身边的手机维修专家
  • 原文地址:https://www.cnblogs.com/LBJLAKERS/p/12114227.html
Copyright © 2020-2023  润新知