SpringCloud-Hystrix服务降级与熔断简介与简单配置

2023-11-03


1、前言

作者最近在学习springcloud,本篇文章仅作为学习笔记,如有错误,敬请指正

2、Hystrix是什么

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

Hystrix包括服务降级与熔断

使用情景

我们可以模拟高并发情况来测试服务,了解Hystrix的使用场景
1)新建模块,导入依赖

<!--hystrix-->
   <dependency>
          <groupId>org.springframework.cloud</groupId>
          <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
           <version>2.2.0.RELEASE</version>
   </dependency>

2)修改appliction.yml配置文件,这里设置为单机Eureka,方便模拟测试

server:
  port: 8001

spring:
  application:
    name: cloud-provider-hystrix-payment

eureka:
  client:
    register-with-eureka: true
    fetch-registry: true
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka

3)在启动类上添加注释@EnableEurekaClient,注册服务

@SpringBootApplication
@EnableEurekaClient
public class PaymentHystrixMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentHystrixMain8001.class,args);
    }
}

4)创建两个service类,里面包含两个方法,其中一个进行线程等待

@Service
public class PaymentService {
    public String paymentInfo_ok(Integer id){
        return "线程池:"+Thread.currentThread().getName()+"paymentInfo_OK,id: "+id+"\t"+"O(∩_∩)O";

    }
    @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = {
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="5000")
    })
    public String paymentInfo_TimeOut(Integer id)
    {

        try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
        return "线程池:"+Thread.currentThread().getName()+"paymentInfo_TimeOut,id: "+id+"\t"+"O(∩_∩)O,耗费3秒";
    }

5)创建controller类,调用service方法

@RestController
@Slf4j
public class PaymentController {
    @Resource
    private PaymentService paymentService;
    @Value("${server.port}")
    private String serverPort;

    @GetMapping("/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id)
    {
        String result = paymentService.paymentInfo_ok(id);
        log.info("****result: "+result);
        return result;
    }

    @GetMapping("/payment/hystrix/timeout/{id}")

    public String paymentInfo_TimeOut(@PathVariable("id") Integer id) throws InterruptedException
    {
        String result = paymentService.paymentInfo_TimeOut(id);
        log.info("****result: "+result);
        return result;
    }

6)开启Jmeter,设置两万次请求并启动
在这里插入图片描述
7)我们手动访问http://localhost:8001/payment/hystrix/ok/1,此时会发现这个测试路径竟然也会等待

8)当然,我们一般是使用EurekaClient端服务消
费者来访问的,我们可以创建一个服务来模拟

主要所需依赖如下

<dependencies>
        <!--openfeign-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-openfeign</artifactId>
        </dependency>
        <!--hystrix-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!--eureka client-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>

配置文件如下

server:
  port: 80

eureka:
  client:
    register-with-eureka: false
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka/

启动类如下

@SpringBootApplication
@EnableFeignClients
public class OrderHystrixMain80
{
    public static void main(String[] args)
    {
        SpringApplication.run(OrderHystrixMain80.class,args);
    }
}

创建Service类,如下

@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT")
public interface PaymentHystrixService
{
    @GetMapping("/payment/hystrix/ok/{id}")
    String paymentInfo_OK(@PathVariable("id") Integer id);

    @GetMapping("/payment/hystrix/timeout/{id}")
    String paymentInfo_TimeOut(@PathVariable("id") Integer id);
}

创建Controller类,如下

@RestController
@Slf4j
public class OrderHystirxController
{
    @Resource
    private PaymentHystrixService paymentHystrixService;

    @GetMapping("/consumer/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id)
    {
        String result = paymentHystrixService.paymentInfo_OK(id);
        return result;
    }

    @GetMapping("/consumer/payment/hystrix/timeout/{id}")
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id)
    {
        String result = paymentHystrixService.paymentInfo_TimeOut(id);
        return result;
    }
}

同理,高并发测试http://localhost/consumer/payment/hystrix/ok/31,会发现一样会有等待。其原因是tomcat的线程已经全部被占

9)结论
正因为有上述故障或不佳表现才有服务降解与熔断等技术的诞生

3 服务降级

	服务降级是当服务器压力剧增的情况下,根据当前业务情况
及流量对一些服务和页面有策略的降级,以此释放服务器资
源以保证核心任务的正常运行

降级配置

1)修改上面8001端口的Service类,加上注解@HystrixCommand和@HystrixProperty

@Service
public class PaymentService {
    public String paymentInfo_ok(Integer id){
        return "线程池:"+Thread.currentThread().getName()+"paymentInfo_OK,id: "+id+"\t"+"O(∩_∩)O";

    }
    @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = {
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1000")
    })
    public String paymentInfo_TimeOut(Integer id)
    {

        try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); }
        return "线程池:"+Thread.currentThread().getName()+"paymentInfo_TimeOut,id: "+id+"\t"+"O(∩_∩)O,耗费3秒";
    }
    public String paymentInfo_TimeOutHandler(Integer id){
        return "/(ㄒoㄒ)/调用支付接口超时或异常:\t"+ "\t当前线程池名字" + Thread.currentThread().getName();
    }

2)在8001端口启动类上添加新注解@EnableCircuitBreaker,激活Hystrix

3)同样进行高并发测试,可以这个时候不会等待,而是会直接执行我们设置的保底方法
在这里插入图片描述

4)同理80端口也可以设置,在80端口的yml配置文件上加上,开启feign上的的Hystrix功能

feign:
  hystrix:
    enabled: true

4)在80端口启动类上添加注解@EnableHystrix,激活Hystrix(@EnableHystrix注解继承了@EnableCircuitBreaker,并对它进行了再封装)
5)修改80端口的Controller类

@RestController
@Slf4j
public class PaymentHystirxController
{
    @Resource
    private PaymentHystrixService paymentHystrixService;

    @GetMapping("/consumer/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id)
    {
        String result = paymentHystrixService.paymentInfo_OK(id);
        return result;
    }

@GetMapping("/consumer/payment/hystrix/timeout/{id}")
@HystrixCommand(fallbackMethod = "paymentTimeOutFallbackMethod",commandProperties = {
        @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="1500")
})
public String paymentInfo_TimeOut(@PathVariable("id") Integer id)
{
    String result = paymentHystrixService.paymentInfo_TimeOut(id);
    return result;
}
public String paymentTimeOutFallbackMethod(@PathVariable("id") Integer id)
{
    return "我是消费者80,对方支付系统繁忙请10秒钟后再试或者自己运行出错请检查自己,o(╥﹏╥)o";
}

}
 

6)结果
在这里插入图片描述
7)问题:这样写fallback方法的话,那么每一个业务方法都需要一个,这会很麻烦,导致代码膨胀

8)解决方法:
在这里插入图片描述
在这里插入图片描述
9)当然,把方法写在业务类里,我觉得不太好,会增加耦合度。解决方法如下,创建一个service实现类
在这里插入图片描述
10)在接口的@FeignClient注解中添加fallback属性,表示使用实现类来进行降级方法的实现
在这里插入图片描述
在这里插入图片描述
11)在测试前记得把Controller中的@HystrixCommand注解删了,才能起效果
在这里插入图片描述

在这里插入图片描述

3、服务熔断

服务熔断的作用类似于我们家用的保险丝,当某服务出现不可用或响应超时的情况时,为了防止整个
系统出现雪崩,暂时停止对该服务的调用。

熔断配置

1)在8001端口服务的Service类上添加如下代码

//=========服务熔断
    @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",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"),//失败率达到多少跳闸
    })
    public String paymentCircuitBreaker(@PathVariable("id") Integer id)
    {
        if(id < 0)
        {
            throw new RuntimeException("******id 不能负数");
        }
        String serialNumber = IdUtil.simpleUUID();

        return Thread.currentThread().getName()+"\t"+"调用成功,流水号: " + serialNumber;
    }
    public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id)
    {
        return "id 不能负数,请稍后再试,/(ㄒoㄒ)/~~   id: " +id;
    }

2)Controller类添加:

@GetMapping("/payment/circuit/{id}")
public String paymentCircuitBreaker(@PathVariable("id") Integer id)
{
    String result = paymentService.paymentCircuitBreaker(id);
    log.info("****result: "+result);
    return result;
}

正常情况:
在这里插入图片描述
异常情况:
在这里插入图片描述
3)测试服务熔断

当我们多次提交错误请求,然后再提交正确请求会发现正确请求也会报错

在这里插入图片描述

服务熔断的三个状态

  • 熔断关闭状态(Closed)

      服务没有故障时,熔断器所处的状态,对调用方的调用不做任何限制。
    
  • 熔断开启状态(Open)

      在固定时间内(Hystrix默认是10秒),接口调用出错比率达到一个阈值(Hystrix默认为50%)
      会进入熔断开 启状态。进入熔断状态后, 后续对该服务接口的调用不再经过网络,直接执
      行本地的fallback方法。
    
  • 半熔断状态(Half-Open)

      在进入熔断开启状态一段时间之后(Hystrix默认是5秒),熔断器会进入半熔断状态。
      所谓半熔断就是尝试恢复服务调用,允许有限的流量调用该服务,并监控调用成功率。
      如果成功率达到预期,则说明服务已恢复,进入熔断关闭状态;如果成功率仍旧很低,则重新进入熔断开启状态。
    

    状态图如下

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

SpringCloud-Hystrix服务降级与熔断简介与简单配置 的相关文章

随机推荐

  • java文件的上传和下载_java文件上传和下载

    在web项目中上传文件夹现在已经成为了一个主流的需求 在OA 或者企业ERP系统中都有类似的需求 上传文件夹并且保留层级结构能够对用户行成很好的引导 用户使用起来也更方便 能够提供更高级的应用支撑 文件夹数据表结构 CREATETABLEI
  • 注解-宋红康

    目录 一 注解 Annotation 概述 二 常见的注解实例 三 如何自定义注解 四 JDK中的四个元注解 五 Java8注解的新特性 1 可重复注解 2 类型注解 一 注解 Annotation 概述 二 常见的注解实例 三 如何自定义
  • Android开发入门组件(十)——WebView

    今天主要写一下WebView 主要是在安卓应用的页面来加载或者写入网页 是比较常见的一种操作 加载网页 1 加载url 网络或者本地assets文件下的html文件 1 加载网络url webview loadUrl 相应的网址 直接在ac
  • 从外包辞职了,600小时后,我入职了字节跳动

    前言 没有绝对的天才 只有持续不断的付出 对于我们每一个平凡人来说 改变命运只能依靠努力 幸运 但如果你不够幸运 那就只能拉高努力的占比 2022年7月 我有幸成为了字节跳动的一名Java后端开发 相信同行都清楚 从外包进大厂有多难 运气之
  • c# --- 泛型解决输入和输出类型不确定问题

    一 背景 有这样一个需求 一个方法 他的返回值类型不确定 方法参数的类型不做要求 二 思考 返回值类型不确定 从继承的角度 所以类都是object的子类 返回object即可 但是这种方法是类型不安全的 需要进行类型转换 我们可以使用泛型解
  • HTML <small> 标签

    定义和用法
  • CUBLAS矩阵乘法

    include
  • Winsock属性 方法介绍

    本文章已收录于 Winsock是Mcrosoft windows提供的网络编程接口 它供了基于TCP IP协议接口实现方法 通过网络进行的数据通信 需要用地址来表示网络中的主机 TCP IP协议使用IP地址来作为主机的标识 实现的连接方式是
  • 关于connect: network is unreachable 问题的解决

    由于发现原创文章 在未署名作者及出处的情况下被转载 在以后所有的原创文章开头我都会写明作者和出处 希望朋友们以后在转载本博客原创博文时注意标明文章作者及出处 作者 liukun321 咕唧咕唧 原文出处 http blog csdn net
  • 牛客面试题库(9)

    请你说说索引怎么实现的B 树 为什么选这个数据结构 说到B 树 一般和B树做对比 都是多叉树 B 数组叶子结点存储数据 其他节点存储索引 而B树每个节点都存储数据 B 树叶子结点内通过单向链表连接 节点和节点之间通过双向链表连接 从磁盘IO
  • 匿名内部类的定义格式

    匿名内部类 1 使用条件 如果接口的实现类 或者父类的子类只需要使用唯一的一次 那么就可以省略该类的定义 改用匿名内部类 2 定义格式 接口名称 对象名 new 接口名称 覆盖重写所有抽象方法 分号不要忘 3 对匿名内部类的格式 new 接
  • springboot + mybatis启动时执行sql脚本

    目录 1 创建数据版本表 结构如下 2 创建HdVersion对象 3 创建执行sql的dao 4 创建dao对应的xml 5 创建sql执行器 实现ApplicationRunner 6 结语 背景 项目开发或发布阶段修改表结构 项目更新
  • 大数据平台测试-白盒测试静态方法解析(我奶奶都能看懂)

    软件测试从某种维度上分为黑盒测试和白盒测试 黑盒测试更多的是增啥改查 也就是功能测试 关于功能测试参考这里 增删改查测试场景 菜市场的大妈都能看懂 关于白盒测试的资料参考这里 白盒测试案例设计 我爷爷都能看懂 注意并不是说白盒测试一定就是要
  • 还不会python 实现常用的数据编码和对称加密?看这篇文章就够啦~

    前 言 相信很多使用 python 的小伙伴在工作中都遇到过 对数据进行相关编码或加密的需求 今天这篇文章主要给大家介绍对于一些常用的数据编码和数据加密的方式 如何使用 python 去实现 话不多说 接下来直接进入主题 1 base64
  • Unity—关节、布料、角色控制器、视频播放

    开学啦 接下来学习Unity的寻路系统和射线 结尾有彩蛋呦 每日一句 少年特有的放浪不羁是青春的定义 目录 关节 布料 视频播放 Character Controller组件 关节 铰链关节 Hinge Joint 将两个刚体 Rigidb
  • jenkins fastlane淌坑记录

    目录 前言 管理证书 使用证书 构建命令 关于app托管 iOS的版本自增 testflight上传 fastlane下苹果的账号验证问题 iOS缓存问题 iOS打包会开启8081服务 fastlane获取最新代码 Fastlane完整代码
  • CSRF漏洞详解

    目录 一 CSRF漏洞原理 1 基本原理 2 流程图 3 条件 二 分类 1 GET型 2 POST型 三 危害 四 检测与防御 1 检测 2 防御 一 CSRF漏洞原理 1 基本原理 CSRF Cross site Request For
  • linux用c++获取mac地址,网卡地址,网口地址,网卡序号ip地址,不使用 ioctl(sock, SIOCGIFCONF, &ifc)获取网络接口名称,这个接口有时会返回-1获取不到,换方法获取

    linux用c 获取mac地址 不使用 ioctl sock SIOCGIFCONF ifc 获取网络接口名称 这个接口有时会返回 1获取不到 换方法获取 1 弃用 SIOCGIFCONF 获取网络接口名称列表 获取所有网络接口列表 ifc
  • # Python推荐系统学习笔记(3)------基于协同过滤的个性化推荐算法实战---隐语义模型

    Python推荐系统学习笔记 3 基于协同过滤的个性化推荐算法实战 隐语义模型 一 概念性理解 传统的推荐方法 UserCF 首先需要找到和他们看了同样书的其他用户 然后给他们推荐那些用户喜欢的其他书 ItemCF 需要给他们推荐和他们已经
  • SpringCloud-Hystrix服务降级与熔断简介与简单配置

    1 前言 作者最近在学习springcloud 本篇文章仅作为学习笔记 如有错误 敬请指正 2 Hystrix是什么 Hystrix是一个用于处理分布式系统的延迟和容错的开源库 在分布式系统里 许多依赖不可避免的会调用失败 比如 超时 异常