SpringCloud入门实战(七)-Hystrix服务降级入门案例

news2024/11/18 13:33:19

📝 学技术、更要掌握学习的方法,一起学习,让进步发生
👩🏻 作者:一只IT攻城狮 。
💐学习建议:1、养成习惯,学习java的任何一个技术,都可以先去官网先看看,更准确、更专业。
💐学习建议:2、然后记住每个技术最关键的特性(通常一句话或者几个字),从主线入手,由浅入深学习。
❤️ 《SpringCloud入门实战系列》解锁SpringCloud主流组件入门应用及关键特性。带你了解SpringCloud主流组件,是如何一战解决微服务诸多难题的。项目demo:源码地址

👉🏻 👉🏻 👉🏻 SpringCloud 入门实战系列不迷路 👈🏻 👈🏻👈🏻:

  • SpringCloud 入门实战(一)什么是SpringCloud?
  • SpringCloud 入门实战(二)-SpringCloud项目搭建
  • SpringCloud 入门实战(三)-Eureka注册中心集成
  • SpringCloud入门 实战(四)-Zookeeper、Consul注册中心集成
  • SpringCloud入门实战(五)-Ribbon负载均衡集成
  • SpringCloud入门实战(六)-OpenFeign服务调用集成
  • SpringCloud入门实战(七)-Hystrix服务降级入门案例

文章目录

  • 一、Hystrix服务降级
  • 二、服务端降级
    • 1、引入Hystrix依赖
    • 2、案例演示
    • 3、服务端如何降级
      • 1)启动类添加激活注解:
      • 2)业务类方法上添加启用:@HystrixCommand(fallbackMethod = "fallback")
  • 三、客户端降级
    • 1、引入Hystrix依赖
    • 2、启动类添加激活注解@EnableHystrix
    • 3、改yml
    • 4、业务类方法上添加启用:@HystrixCommand(fallbackMethod = "fallback")
  • 四、全局通用服务降级
    • 1、类上加注解:DefaultProperties(defaultFallback=" ")指定全局兜底方法
    • 2、方法加注解:@HystrixCommand
    • 3、编写全局降级方法
  • 五、解耦服务降级
    • 1、新建一个解耦降级处理类
    • 2、Feign客户端定义的接口添加fallback

Hystrix关键特性:服务降级、服务熔断、服务限流

一、Hystrix服务降级

服务降级:也就是假设对方系统不可用了,向调用方返回一个符合预期的,可备选的响应。比如我们常见的“服务器忙,请稍后重试!”、“系统开小差,请稍后再试!”、“您的内容飞到了外太空…”等,超时不再等待,出错有兜底方案。不用客户等待并立刻返回一个友好的提示,这就是服务降级。

出现服务降级的情况
①程序运行异常;
②超时;
③服务熔断触发服务降级;
④线程池/信号量打满也会导致服务降级。

解决方案
对方服务超时了或宕机,调用者不能一直卡死等待,必须有服务降级;
对方服务可能OK,调用者自己出故障或有自我要求(自己的等待时间小于服务提供者),自己服务降级。

二、服务端降级

在springcloud项目中,技术实现上来说Hystrix服务降级放在服务端、客户端均可以,具体根据自己的业务场景判定,但是一般Hystrix服务降级fallback是放在客户端,这里我们均演示一下。

项目结构:

在这里插入图片描述

父工程的版本环境:

 <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-dependencies</artifactId>
        <version>2021.0.3</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      <dependency>
        <groupId>com.alibaba.cloud</groupId>
        <artifactId>spring-cloud-alibaba-dependencies</artifactId>
        <version>2.2.7.RELEASE</version>
        <type>pom</type>
        <scope>import</scope>
      </dependency>
      <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-dependencies</artifactId>
        <version>2.7.1</version>
        <type>pom</type>
        <scope>import</scope>
</dependency>

1、引入Hystrix依赖

首先服务端(也就是我们的payment工程)引入hystrix依赖(具体版本根据自己环境决定):

   <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
            <version>2.2.1.RELEASE</version>
        </dependency>
        <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-javanica</artifactId>
            <version>1.5.18</version>
    </dependency>

2、案例演示

Controller类代码:

@RestController
@RequestMapping("/payment")
@Slf4j
public class PaymentController {
    @Resource
    private PaymentService paymentService;

    @GetMapping(value = "/hystrix/ok/{id}")
    public String paymentInfoOk(@PathVariable("id") Integer id) {
        String result = paymentService.paymentInfoOk(id);
        log.info("========result:{}========", result);
        return result;
    }
    @GetMapping(value = "/hystrix/timeout/{id}")
    public String paymentInfoTimeOut(@PathVariable("id") Integer id) {
        String result = paymentService.paymentInfoTimeOut(id);
        log.info("========result:{}========", result);
        return result;
    }
}

服务端业务类简单编写两个方法:一个正常查询方法,一个模拟复查业务耗时的方法:

@Service
public class PaymentServiceImpl extends ServiceImpl<PaymentMapper, Payment> implements PaymentService {

    @Override
    public String paymentInfoOk(Integer id) {
        return "线程池:" + Thread.currentThread().getName() + "成功访问paymentInfoOK,id=" + id;
    }

    @Override
    public String paymentInfoTimeOut(Integer id) {
        int time = 5;
        try {
            TimeUnit.SECONDS.sleep(time);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        return "线程池:" + Thread.currentThread().getName() +  "耗时" + time + "秒成功访问paymentInfoTimeOut,id=" + id;
    }
}

简单测试:两个接口都正常访问和返回:
http://localhost:8001/payment/hystrix/ok/1 直接返回
http://localhost:8001/payment/hystrix/timeout/1 等待5s返回(转圈圈一下)

并发请求:接下来通过jmeter压测接口:http://localhost:8001/payment/hystrix/timeout/1,模拟2w个请求访问我们的paymentInfoTimeOut耗时业务接口。

现象:发现两个接口都会转圈甚至卡死,我们发现正常直接返回结果的接口也会被同一个微服务里耗时接口拖垮。所以想要系统高可用必须降级处理。假设payment服务端业务逻辑实际处理需要5s,微服务对自身有要求,超过3s作超时处理,也是需要降级的。

原因:SpringBoot默认集成的是tomcat,tomcat的默认工作线程(10个)被打满了,没有多余的线程来分解压力和处理。

3、服务端如何降级

1)启动类添加激活注解:

@EnableCircuitBreaker

有的环境会提示@EnableCircuitBreaker is deprecated已弃用,用@EnableHystrix注解代替即可。

本demo环境使用的是@EnableHystrix激活注解

2)业务类方法上添加启用:@HystrixCommand(fallbackMethod = “fallback”)

在fallbackMethod中添加一个方法,value设置为超时时间,当超过超时时间时,就会调用备用的方法

注:降级(FallBack)方法必须与其对应的业务方法在同一个类中,否则无法生效。

@RestController
@RequestMapping("/payment")
@Slf4j
public class PaymentController {
    @Resource
    private PaymentService paymentService;

    @GetMapping(value = "/hystrix/ok/{id}")
    public String paymentInfoOk(@PathVariable("id") Integer id) {
        String result = paymentService.paymentInfoOk(id);
        log.info("========result:{}========", result);
        return result;
    }
    //设置超时时间3s
    @HystrixCommand(fallbackMethod = "fallback",commandProperties = {
            @HystrixProperty(name ="execution.isolation.thread.timeoutInMilliseconds",value = "3000")
    })
    @GetMapping(value = "/hystrix/timeout/{id}")
    public String paymentInfoTimeOut(@PathVariable("id") Integer id) {
        String result = paymentService.paymentInfoTimeOut(id);
        log.info("========result:{}========", result);
        return result;
    }
    public String fallback(Integer id){
        return "系统繁忙,请稍后再试!线程池:" + Thread.currentThread().getName() +"访问paymentInfoTimeOut,id=" + id;

    }
}

测试降级效果:

不会再等待5s,到达设置的超时时间3s就会调用降级方法。

Tip:如果不设置超时时间,Hystrix默认超时时间是1秒,我们可以通过hystrix源码看到:找到 hystrix-core.jar包下的HystrixCommandProperties类中的default_executionTimeoutInMilliseconds属性局势默认的超时时间:1000

三、客户端降级

我们将服务端payment工程刚做的操作恢复到没有任何降级处理的状态,开始演示客户端降级。

1、引入Hystrix依赖

客户端工程order同样的操作引入Hystrix依赖:

  <dependency>
           <groupId>org.springframework.cloud</groupId>
           <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
           <version>2.2.1.RELEASE</version>
       </dependency>
       <dependency>
           <groupId>com.netflix.hystrix</groupId>
           <artifactId>hystrix-javanica</artifactId>
           <version>1.5.18</version>
   </dependency>

2、启动类添加激活注解@EnableHystrix

@SpringBootApplication(exclude = {DataSourceAutoConfiguration.class})
@EnableDiscoveryClient
@EnableHystrix
public class CloudOrder {
    public static void main(String[] args) {
        SpringApplication.run(CloudOrder.class, args);
    }
}

3、改yml

我们的客户端是通过feign调用服务端,所以在order工程中修改yml,添加内容:

feign:
  hystrix:
    enabled: true

4、业务类方法上添加启用:@HystrixCommand(fallbackMethod = “fallback”)

添加:@HystrixCommand(fallbackMethod = “fallback”,commandProperties = {@HystrixProperty(name =“execution.isolation.thread.timeoutInMilliseconds”,value = “1500”) })及fallback方法:

@RestController
@RequestMapping("/order")
@Slf4j
@DefaultProperties(defaultFallback="globalFallback")
public class OrderHystrixController {
    @Resource
    private PaymentHystrixService paymentHystrixService;

    @GetMapping(value = "/hystrix/ok/{id}")
    public String paymentInfoOk(@PathVariable("id") Integer id) {
        String result = paymentHystrixService.paymentInfoOk(id);
        log.info("========result:{}========", result);
        return result;
    }

   @HystrixCommand(fallbackMethod = "fallback",commandProperties = {
            @HystrixProperty(name ="execution.isolation.thread.timeoutInMilliseconds",value = "1500")
    })
    @GetMapping(value = "/hystrix/timeout/{id}")
    public String paymentInfoTimeOut(@PathVariable("id") Integer id) {
        String result = paymentHystrixService.paymentInfoTimeOut(id);
        log.info("========result:{}========", result);
        return result;
    }
    public String fallback(Integer id){
        return "太久了我不想等待了,我已经等待了1.5s了!线程池:" + Thread.currentThread().getName() +"访问paymentInfoTimeOut,id=" + id;

    }
}

Feign接口:

@Component
@FeignClient(value = "CLOUD-PAYMENT",fallback = PaymentFallbackService.class)
public interface PaymentHystrixService {

    @GetMapping(value = "/payment/hystrix/ok/{id}")
    String paymentInfoOk(@PathVariable("id") Integer id);

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

客户端测试调用服务端超时降级:

我们发现方法一对一降级,那样代码将越来越多,越来越重复,代码膨胀,所以要设置全局通用服务降级方法。

四、全局通用服务降级

避免代码膨胀,我们设置全局通用服务降级方法,如果需要特殊配置的在另外单独配。

小结:如果注解@HystrixCommand定义fallback方法,走自己定义的fallback方法,反之走全局默认的@DefaultProperties中指定的方法。
总之:全局降级方法的优先级较低,只有业务方法没有指定其降级方法时,服务降级时才会触发全局回退方法。若业务方法指定它自己的回退方法,那么在服务降级时,就只会直接触发它自己的回退方法,而非全局回退方法。

1、类上加注解:DefaultProperties(defaultFallback=" ")指定全局兜底方法

2、方法加注解:@HystrixCommand

3、编写全局降级方法

@RestController
@RequestMapping("/order")
@Slf4j
@DefaultProperties(defaultFallback="globalFallback")
public class OrderHystrixController {
    @Resource
    private PaymentHystrixService paymentHystrixService;

    @GetMapping(value = "/hystrix/ok/{id}")
    public String paymentInfoOk(@PathVariable("id") Integer id) {
        String result = paymentHystrixService.paymentInfoOk(id);
        log.info("========result:{}========", result);
        return result;
    }

    @HystrixCommand
    @GetMapping(value = "/hystrix/timeout/{id}")
    public String paymentInfoTimeOut(@PathVariable("id") Integer id) {
        String result = paymentHystrixService.paymentInfoTimeOut(id);
        log.info("========result:{}========", result);
        return result;
    }

    //全局方法降级
    public String globalFallback(){
        return "全局降级!线程池:" + Thread.currentThread().getName() +"访问paymentInfoTimeOut";

    }
}

测试客户端全局降级:

继续思考,所有的降级都在Controller层处理是不是耦合度很高,服务降级每个方法都添加hyxtrix兜底的方法,造成方法的膨胀,既然是服务间的调用,我们能不能将和服务端工程相关的feign接口整体降级,也就是和payment工程相关的都统一降级。

五、解耦服务降级

只需要为Feign客户端定义的接口添加一个服务降级处理的实现类即可实现解耦,也就是@FeignClient注解修饰的这个调用类。

1、新建一个解耦降级处理类

新建一个解耦降级处理类PaymentFallbackService.java,该类实现@FeignClient修饰的PaymentHystrixService接口:

@Component
public class PaymentFallbackService implements PaymentHystrixService {
    @Override
    public String paymentInfoOk(Integer id) {
        return "全局解耦降级处理PaymentFallback->paymentInfoOk!";
    }

    @Override
    public String paymentInfoTimeOut(Integer id) {
        return "全局解耦降级处理PaymentFallback->paymentInfoTimeOut!";
    }
}

2、Feign客户端定义的接口添加fallback

Feign客户端定义的接口PaymentHystrixService.java中添加fallback = PaymentFallbackService.class

@Component
@FeignClient(value = "CLOUD-PAYMENT",fallback = PaymentFallbackService.class)
public interface PaymentHystrixService {

    @GetMapping(value = "/payment/hystrix/ok/{id}")
    String paymentInfoOk(@PathVariable("id") Integer id);

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

3、测试降级

Tip:如果不生效,检查该实现类是否以组件的形式添加 Spring 容器中,最常用的方式就是在类上标注 @Service注解或者@Component注解。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/451584.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

广州华锐互动:AR远程协作系统为电力设备状态监测提供有力支持

电力设备是电网运行的重要组成部分&#xff0c;对电网的安全稳定运行具有至关重要的作用。在电力设备状态监测中&#xff0c;如何快速、准确地诊断和解决设备故障&#xff0c;是电力企业和电力设备维护人员需要面对的重要问题。 广州华锐互动将AR增强现实技术运用到电力设备维…

美颜sdk是什么?探索美颜sdk的技术内幕

目前&#xff0c;美颜sdk作为美颜功能的实现方式&#xff0c;已经成为了各大应用开发者的热门选择之一。那么&#xff0c;美颜sdk到底是什么&#xff1f;它的技术内幕又是怎样的呢&#xff1f;本文将会为您揭开它的神秘面纱。 一、美颜sdk简述 美颜sdk顾名思义&#xff0c;就…

瑞萨开发环境搭建

使用keil环境&#xff0c;开发瑞萨renase A4M2 下载MDK 下载MDK&#xff0c;5.37 其它版本 最好使用5.30以上 [外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-5k3XGSK5-1682182139410)(https://secure2.wostatic.cn/static/reEunrWa2vsfrcpVZC1nbo…

关于存储那些事1-----基础篇

目录 一、SSD1、简介1.1 分类1.1.1 易失性存储器1.1.2 非易失性存储器 2、SSD接口2.1 SATA接口2.2 SATA Express接口2.3 SAS接口2.4 U.2接口2.5 mSATA接口2.6 M.2接口2.7 PCI-E接口 二、闪存&#xff08;Flash memory&#xff09;1、简介1.1 NOR Flash1.2 NAND Falsh1.3 NOR Fl…

二维码图片生成工具C#winform源码

二维码图片生成工具C#winform源码 源码描述&#xff1a; 一、源码特点 采用winform进行开发,生成二维码并保存&#xff0c;欢迎下载 二、功能介绍 本源码是一个可以自动生成二维码图片的小模块&#xff0c;可以添加自己的logo图片&#xff0c;可以保存在自己想要保存的地方 …

ubuntu20.04+x86_64+virtualbox6.7 环境下编译xenomai内核和实时性测试[详解]

下面是针对实时系统Xenomai使用的一些记录,实时系统在工业自动化,机器人等智能行业是必需会用到的。 简述 xenomai是众多inux实时性解决方案中的一种,通过在linux的基础上添加一个RTOS内核cobalt,来提高linux的实时性。实时内核cobalt与非实时内核linux相结合,既能提供工…

C/C++笔记-写一个Makefile并链接QtCore库使用QString,QDebug

如下cpp代码&#xff0c;调用QDebug打印程序&#xff1a; #include <QDebug> #include <QString>int main(int argc, char *argv[]){QString testStr "hello";qDebug() << testStr;return 0; } 如下makefile&#xff1a; test: main.cppg -c -…

‘gulp‘ 不是内部或外部命令,也不是可运行的程序

出现问题&#xff1a; D:\git\renwey-web-mobile>gulp default gulp 不是内部或外部命令&#xff0c;也不是可运行的程序 或批处理文件。 两种原因 原因一&#xff1a;环境变量没有设置 原因二&#xff1a;没有安装全局的gulp&#xff0c;只安装了本地gulp&#xff0c;…

CTFShow-Web篇详细wp

CTFShow-Web篇详细wp web签到题web2web3web4web5web6web7web8 CTFShow 平台&#xff1a;https://ctf.show/ web签到题 直接F12然后Base64解码 ctfshow{19bdf375-f974-481e-8c62-0f4c3d170fb4} web2 考点&#xff1a;联合查询 先尝试使用万能密码登入 ‘ or 11# 登入成功&am…

NFS共享服务

文章目录 1.NFS1.1 NFS简介1.2 RPC简介1.3 NFS网络文件系统1.4 NFS应用场景1.5 NFS通讯原理 2.NFS配置 1.NFS 1.1 NFS简介 NFS&#xff08;Network File System&#xff09;即网络文件系统&#xff0c;是FreeBSD支持的文件系统中的一种&#xff0c;它允许网络中的计算机之间通…

产品的技术加油站

作为产品经理的你&#xff0c;每次被喷不懂技术的时候&#xff0c;是否也曾想过暗暗发力&#xff0c;恶补一波技术&#xff0c;然后惊艳所有人&#xff1f;但冷静之后&#xff0c;又觉得无从下手&#xff1f; 是不是还想过要不要学习一下编程&#xff1f;然后被人推荐了什么py…

【致敬未来的攻城狮计划】— 连续打卡第十天:FSP固件库开发及FSP配置详解。

系列文章目录 1.连续打卡第一天&#xff1a;提前对CPK_RA2E1是瑞萨RA系列开发板的初体验&#xff0c;了解一下 2.开发环境的选择和调试&#xff08;从零开始&#xff0c;加油&#xff09; 3.欲速则不达&#xff0c;今天是对RA2E1 基础知识的补充学习。 4.e2 studio 使用教程 5.…

Gnuplot绘图入门2——根据多列文本数据绘制图形

Gnuplot绘图入门2——根据多列文本数据绘制图形 Gnuplot绘图入门1以绘制sin(x)的函数图形为例&#xff0c;对Gnuplot进行了简要介绍。这个教程将介绍如何使用Gnuplot对保存在文本文件&#xff08;.txt、.dat文件&#xff09;中的数据进行可视化。 将下面的数据复制下了&#…

Python高光谱遥感数据处理与机器学习实践技术

目录 第一章 高光谱基础 第二章 高光谱开发基础&#xff08;Python&#xff09; 第三章 高光谱机器学习技术&#xff08;python&#xff09; 第四章 典型案例操作实践 总结了高光谱遥感技术领域的基础原理与核心概念&#xff0c;采用编程语言复现经典数据处理和应用方法&am…

OpenHarmony应用开发-ArkUI方舟开发框架简析

方舟开发框架&#xff08;简称ArkUI&#xff09;为OpenHarmony应用的UI开发提供了完整的基础设施&#xff0c;包括简洁的UI语法、丰富的UI功能&#xff08;组件、布局、动画以及交互事件&#xff09;&#xff0c;以及实时界面预览工具等&#xff0c;可以支持开发者进行可视化界…

ChatGPT会被人工智能干掉吗?

01 ChatGPT火爆全球 ChatGPT是美国“开放人工智能研究中心”2022年11月30日发布的聊天机器人程序&#xff0c;它是人工智能技术驱动的自然语言处理工具&#xff0c;能通过学习和理解人类的语言来进行对话&#xff0c;还能根据聊天的上下文进行互动&#xff0c;真正像人类一样…

pcl中MomentOfInertiaEstimation计算有向包围盒

pcl::MomentOfInertiaEstimation 是 Point Cloud Library (PCL) 中的一个类&#xff0c;用于计算点云中物体的矩。它可以提供点云物体的三个主轴及其长度&#xff0c;以及物体的惯性矩阵等信息。通过使用 pcl::MomentOfInertiaEstimation 类&#xff0c;可以实现物体形状分析、…

C++类和对象-3

承接上一篇博客中内容&#xff0c;讲述完类和对象中构造函数内容之后&#xff0c;这篇博客我们来讲述类和对象中&#xff0c;析构函数的内容。 目录 1.析构函数 2.拷贝构造函数 3.浅拷贝与深拷贝 1.析构函数 在类和对象的构建当中&#xff0c;类中的对象会通过构造函数来…

Jenkins配置邮箱发送报告

本文以qq邮箱为例 1.下载Email Extension Plugin插件 2.在Manage Jenkins--System&#xff0c;Jenkins Location下配置理员邮件 Extended E-mail Notification 下配置Jenkins SMTP server&#xff08;邮箱服务&#xff09;、SMTP Port&#xff08;邮箱端口&#xff09;、Cred…

c++学习(day4)

文章目录 一. 友元&#xff08;friend&#xff09;1 友元函数1.1 全局函数作为友元函数1.2 类的成员函数作为友元函数&#xff08;了解&#xff09; 2. 友元类3. 使用友元的注意事项 二. 常成员函数和常对象&#xff08;const&#xff09;1. 常成员函数2. 常对象3. mutable关键…