ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

08-SpringCloud 之 Hystrix

2022-05-28 23:02:07  阅读:177  来源: 互联网

标签:hystrix Hystrix SpringCloud 08 springframework public import org id


什么是 Hystrix

  • Hystrix 即:服务熔断器,是用来处理分布式系统的延迟和容错的开源库。
  • 在分布式系统中,服务之间的调用会不可避免的调用失败,如超时、异常等,Hystrix 是用来保证在一个依赖出现问题时,不会导致整体服务的失败,避免级联故障的发生,从而提高分布式系统的弹性。

熔断机制

  • 熔断机制是对应雪崩效应的一种微服务的链路保护机制
  • 当某个服务发生故障,对该服务的请求就会出现失败、超时等问题,此时系统自动开启熔断器,之后此服务不再提供任何业务操作,所有对该服务的请求都会快速失败,直接返回失败信息;这样的话依赖于该服务的其他服务就不会因为得不到回应而造成线程阻塞,从而避免级联故障。

服务熔断与服务降级

  • 服务熔断发生在服务端,就是事先为服务端的方法提供一个备选方案,当该方法出现异常的时候,备选方案自动顶替上去,备选方案返回值与原方法返回值一致,这样就不会导致整个系统奔溃
  • 服务降级发生在客户端,如双 11、618 等大型电商活动期间,导致后端服务器压力剧增,此时可以根据具体业务及流量情况,选择性的关闭一些与活动期间无关的非核心业务,从而释放更多的资源来保证核心业务的正常运作;服务关闭后,客户端将不再进行服务调用而直接返回缺省值

Hystrix 服务熔断配置

服务熔断发生在服务端,重点配置 Provider

  1. Provider 的 pom 中添加依赖

    pom.xml
    <!-- Hystrix -->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-hystrix</artifactId>
    </dependency>
    
  2. Provider 新建 Controller 定义常规方法并通过 @HystrixCommand 注解为其配置熔断回调方法

    DeptHystrixController
    package com.kaishen.controller;
    
    import com.kaishen.pojo.Dept;
    import com.kaishen.service.DeptService;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.annotation.Resource;
    
    /**
     * 部门服务 Hystrix 控制层
     * @author : toby
     * Create in 13:38 2022/5/9
     */
    @RestController
    @Slf4j
    public class DeptHystrixController {
    
        @Resource
        private DeptService deptService;
    
        /**
         * 根据部门编号查询部门信息
         * @param id 部门编号
         * @return 返回部门信息
         */
        @GetMapping("/hystrix/dept/get/{id}")
        @HystrixCommand(fallbackMethod = "hystrixQueryDeptById")
        public Dept fusingQueryDeptById(@PathVariable Long id) {
            // 调用查询方法
            Dept dept = deptService.queryDeptById(id);
    
            log.info("hystrix 查询结果:" + dept);
    
            if (null == dept) {
                throw new RuntimeException("查询异常");
            }
            return dept;
        }
    
        /**
         * 部门查询熔断方法
         * @param id 部门编号
         * @return 返回构建的部门实体
         */
        @SuppressWarnings("unused")
        public Dept hystrixQueryDeptById(@PathVariable Long id) {
            return new Dept().setDeptNo(id)
                    .setDeptName("根据 id = " + id + " 查不到对应的部门信息,此处返回熔断信息")
                    .setDbSource("没有数据来源");
        }
    }
    
  3. 启动类开启熔断器 @EnableCircuitBreaker

  4. Consumer 中通过 Feign 正常调用即可

Hystrix 服务降级配置

服务降级发生在客户端,重点配置 Consumer

  1. Consumer 端新增接口

    DeptHystrixDemotionService
    package com.kaishen.feign.service;
    
    import com.kaishen.pojo.Dept;
    import org.springframework.cloud.openfeign.FeignClient;
    import org.springframework.stereotype.Component;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    
    /**
     * 支持服务降级的接口
     * @author : toby
     * Create in 16:52 2022/5/9
     */
    @Component
    @FeignClient(value = "SPRING-CLOUD-PROVIDER-DEPT", contextId = "3", fallbackFactory = DeptHystrixDemotionServiceFallbackFactory.class)
    public interface DeptHystrixDemotionService {
    
        /**
         * 根据部门编号查询部门信息
         *  -- 支持服务降级
         *  -- application.yml 中开启服务降级后不会再去访问后端系统,此处测试降级功能省略后端方法
         * @param id 部门编号
         * @return 返回部门信息
         */
        @GetMapping("/demotion/dept/get/{id}")
        Dept demotionQueryDeptById(@PathVariable("id") Long id);
    
        /**
         * 说 Hello
         *  -- 定义多个方法,以供回调工厂处理
         */
        @GetMapping("demotion/hello")
        void sayHello();
    }
    
  2. 自定义工厂类,实现 FallbackFactory 接口,将新建的接口作为泛型传入,重写 create 方法

    DeptHystrixDemotionServiceFallbackFactory
    package com.kaishen.feign.service;
    
    import com.kaishen.pojo.Dept;
    import feign.hystrix.FallbackFactory;
    import org.springframework.stereotype.Component;
    
    /**
     * 支持服务降级的回调工厂
     * @author : toby
     * Create in 16:57 2022/5/9
     */
    @Component
    public class DeptHystrixDemotionServiceFallbackFactory implements FallbackFactory<DeptHystrixDemotionService> {
        @Override
        public DeptHystrixDemotionService create(Throwable cause) {
            return new DeptHystrixDemotionService() {
                @Override
                public Dept demotionQueryDeptById(Long id) {
                    return new Dept().setDeptNo(id)
                            .setDeptName("洪峰期,暂不提供此服务")
                            .setDbSource("没有数据来源");
                }
    
                @Override
                public void sayHello() {
                    System.out.println("秒杀时刻,服务降级,暂不提供此服务");
                }
            };
        }
    }
    
  3. 在新增的接口中开启 Feign 注解,并通过 fallbackFactory 属性指向降级回调工厂 @FeignClient(value = "SPRING-CLOUD-PROVIDER-DEPT", contextId = "3", fallbackFactory = DeptHystrixDemotionServiceFallbackFactory.class)

  4. application.yml 中开启降级

    application.yml
    # Feign 配置
    feign:
      hystrix:
        enabled: true # 开启服务降级
    

Hystrix Dashboard

  1. 新建 Module:spring-cloud-dashboard-9001

  2. 编写 pom 引入依赖

    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>spring-cloud-netflix</artifactId>
            <groupId>com.kaishen</groupId>
            <version>1.0-SNAPSHOT</version>
        </parent>
        <modelVersion>4.0.0</modelVersion>
    
        <artifactId>spring-cloud-dashboard-9001</artifactId>
    
        <properties>
            <maven.compiler.source>8</maven.compiler.source>
            <maven.compiler.target>8</maven.compiler.target>
        </properties>
    
        <!-- 引入该模块所需依赖 -->
        <dependencies>
            <!-- Dashboard -->
            <dependency>
                <groupId>org.springframework.cloud</groupId>
                <artifactId>spring-cloud-starter-hystrix-dashboard</artifactId>
            </dependency>
        </dependencies>
    </project>
    
  3. 编写 application.yml

    application.yml
    server:
      port: 9001
    
    # Spring 配置
    spring:
      application:
        name: spring-cloud-dashboard9001
    
    # Dashboard 配置
    hystrix:
      dashboard:
        proxy-stream-allow-list: "*" # 允许代理的主机列表
    
  4. 编写启动类,开启注解

    DashboardApplication9001
    package com.kaishen;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;
    
    /**
     * 监控服务启动类
     * @author : toby
     * Create in 19:24 2022/5/9
     */
    @SpringBootApplication
    @EnableHystrixDashboard
    public class DashboardApplication9001 {
    
        public static void main(String[] args) {
            SpringApplication.run(DashboardApplication9001.class, args);
        }
    }
    
  5. 启动 Dashboard 可看到如下界面,则 Dashboard 配置成功
    Dashboard

  6. 被监控的服务中需要引入 actuator 及 Hystrix 依赖

    pom.xml
    <!-- SpringBoot 监控 -->
    <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>
    
  7. 被监控服务的启动类中添加 hystrixMetricsStreamServlet,并开启 @EnableHystrix 注解

    DeptHystrixProviderApplication8004
    package com.kaishen;
    
    import com.netflix.hystrix.contrib.metrics.eventstream.HystrixMetricsStreamServlet;
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    import org.springframework.boot.web.servlet.ServletRegistrationBean;
    import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
    import org.springframework.cloud.netflix.hystrix.EnableHystrix;
    import org.springframework.context.annotation.Bean;
    
    /**
     * 部门服务提供者启动类
     * @author : toby
     * Create in 10:56 2022/5/10
     */
    @SpringBootApplication
    @EnableEurekaClient
    @EnableHystrix
    public class DeptHystrixProviderApplication8004 {
    
        public static void main(String[] args) {
            SpringApplication.run(DeptHystrixProviderApplication8004.class, args);
        }
    
        /**
         * 注册监控页面
         * @return hystrixMetricsStreamServletServletRegistrationBean
         */
        @Bean
        public ServletRegistrationBean<HystrixMetricsStreamServlet> hystrixMetricsStreamServlet() {
            ServletRegistrationBean<HystrixMetricsStreamServlet> hystrixMetricsStreamServletServletRegistrationBean = new ServletRegistrationBean<>(new HystrixMetricsStreamServlet());
            hystrixMetricsStreamServletServletRegistrationBean.addUrlMappings("/actuator/hystrix.stream");
            return hystrixMetricsStreamServletServletRegistrationBean;
        }
    }
    

    注意注意注意

    • 被监控服务 Controller 中的所有方法都必须要有 @HystrixCommand() 熔断实现,否则 Dashboard 无法正常显示
    • 先对被监控服务进行一次正常访问如:http://localhost:8004/hystrix/dept/get/1
  8. 被监控服务的 Controller

    DeptHystrixController
    package com.kaishen.controller;
    
    import com.kaishen.pojo.Dept;
    import com.kaishen.service.DeptService;
    import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
    import lombok.extern.slf4j.Slf4j;
    import org.springframework.web.bind.annotation.GetMapping;
    import org.springframework.web.bind.annotation.PathVariable;
    import org.springframework.web.bind.annotation.RestController;
    
    import javax.annotation.Resource;
    
    /**
     * 部门服务 Hystrix 控制层
     * @author : toby
     * Create in 13:40 2022/5/9
     */
    @RestController
    @Slf4j
    public class DeptHystrixController {
    
        @Resource
        private DeptService deptService;
    
        // region fusingQueryDeptById
        /**
         * 根据部门编号查询部门信息
         * @param id 部门编号
         * @return 返回部门信息
         */
        @GetMapping("/hystrix/dept/get/{id}")
        @HystrixCommand(fallbackMethod = "hystrixQueryDeptById")
        public Dept fusingQueryDeptById(@PathVariable Long id) {
            // 调用查询方法
            Dept dept = deptService.queryDeptById(id);
    
            log.info("hystrix 查询结果:" + dept);
    
            if (null == dept) {
                throw new RuntimeException("查询异常");
            }
            return dept;
        }
    
        /**
         * 部门查询熔断方法
         * @param id 部门编号
         * @return 返回构建的部门实体
         */
        @SuppressWarnings("unused")
        public Dept hystrixQueryDeptById(@PathVariable Long id) {
            return new Dept().setDeptNo(id)
                    .setDeptName("根据 id = " + id + " 查不到对应的部门信息,此处返回熔断信息")
                    .setDbSource("没有数据来源");
        }
        // endregion
    
        // region sayHello
        /**
         * 说 Hello
         *  此方法无意义,只用于定义多个方法供回调工厂处理
         * @param id 入参
         * @return 返回字符串
         */
        @GetMapping("/hystrix/dept/get/map/{id}")
        @HystrixCommand(fallbackMethod = "toSayHello")
        public String sayHello(@PathVariable Long id) {
    
            int i = 2;
    
            if (id == i) {
                throw new RuntimeException("报错啦");
            }
            System.out.println("Hello");
            return "Hello";
        }
    
        @SuppressWarnings("unused")
        public String toSayHello(@PathVariable Long id) {
            System.out.println(id);
            return "toSayHello";
        }
        // endregion
    }
    
  9. 在 Dashboard 界面,填写要被监控的流信息,如下图
    Dashboard

  10. 进入后即可看到监控页面
    监控页面

标签:hystrix,Hystrix,SpringCloud,08,springframework,public,import,org,id
来源: https://www.cnblogs.com/xiaokai007/p/16321731.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有