Hystrix

初识Hystrix

Hystrix是什么?

  Java应用程序讲求“高内聚低耦合”,而spring cloud是一种微服务架构理念,将原来的一个应用程序拆分成许多微服务来调用,这样的话就可以满足“低耦合”的要求,但是随之而来的就是“服务雪崩”问题。

  所谓的服务雪崩就是指,由于服务提供者不可用导致服务调用者不可用,并且在生产过程中,这种不可用逐渐扩大的现象。想要解决“服务雪崩”问题就需要用到Hystrix(豪猪)

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

  "断路器”本身是一种开关装置,当某个服务单元发生故障之后,通过断路器的故障监控(类似熔断保险丝),向调用方返回一个符合预期的、可处理的备选响应(FallBack),而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间、不必要地占用,从而避免了故障在分布式系统中的蔓延,乃至雪崩。

Hystrix三大概念

服务降级(fallback)

fallback是什么

  所谓的服务降级就是当服务出现程序运行异常、超时、服务熔断触发服务降级、线程池/信号量打满等情况,此时应该返回一个符合预期的、可处理的备选响应(fallback),以提高用户的使用体验而不是长时间的等待请求或者返回一个超时异常页面。总而言之,当出现以上问题时,要有一个兜底方案来提高用户的使用体验

  服务降级的解决方案可以分为服务提供方和服务调用方,两面都可以实现服务降级

服务提供方实现服务降级

  第一步: 对服务提供方的service接口方法进行加强,主要就是针对可能出现超时等异常情况的接口,新建方法对其进行兜底,如果原接口出现问题则使用兜底方案进行反馈

  使用@HystrixCommand注解的fallbackMethod属性指定兜底方法名,使用commandProperties属性的@HystrixProperty注解指定异常类型(超时异常和超时时间)

/**
 * 超时访问,设置自身调用超时的峰值,峰值内正常运行,超过了峰值需要服务降级 自动调用fallbackMethod 指定的方法
 * 超时异常或者运行异常 都会进行服务降级
 * @param id
 * @return
 */
@HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler", commandProperties = {
        @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "3000")
})
public String paymentInfoTimeOut(Integer id) {
    int second = 5;
    try {
        TimeUnit.SECONDS.sleep(second);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "线程池:  "   Thread.currentThread().getName()   " paymentInfoTimeOut,id:  "   id   "\t"
              "O(∩_∩)O哈哈~"   "  耗时(秒): "   second;
}
public String paymentInfo_TimeOutHandler(Integer id) {
    return "超时异常兜底方案!线程池:  "   Thread.currentThread().getName()   " paymentInfo_TimeOutHandler,id:  "   id   "\t";
}

  第二步: 服务提供方的主启动类上使用@EnableCircuitBreaker注解开启“熔断器”,这样的话前面的配置才能生效

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

  除了上述可以自定义超时时间的异常,出现其他运行时异常也会调用兜底方案返回

服务调用方实现服务降级

  第一步: 使用配置文件开启hystrix

feign:
  hystrix:
    enabled: true

  第二步: 服务调用方的controller加强,新建方法对其进行兜底,使用方式与服务提供方一样,主要就是服务调用方和服务提供方两套方案,可以实现两边定制化。

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

  第三步: 服务调用方的主程序类上使用@EnableHystrix注解开启hystrix

服务降级优化

  • 解决冗余问题

  前面的每一个方法都对应一个兜底方案,这样的话会显得代码十分臃肿,实际上很多的接口都可以使用一个兜底方案,于是我们就可以配置默认的兜底方案,在没有使用@HystrixCommand注解指定的时候,类中的所有接口都会走默认兜底方案

  @DefaultProperties注解的defaultFallback属性指定默认兜底方法,如果类中存在@HystrixCommand注解中不使用属性指定特定兜底方案的情况,就说明这个接口使用是默认兜底方案

@RestController
@RequestMapping("consumer")
@Slf4j
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
public class OrderHystrixController {
    @Resource
    private PaymentHystrixService paymentHystrixService;
    @HystrixCommand
    @GetMapping("/payment/hystrix/ex/{id}")
    public String paymentInfoException(@PathVariable("id") Integer id) {
        int age = 10/0;
        String result = paymentHystrixService.paymentInfoException(id);
        return result;
    }
    /**
     * hystrix 全局fallback方法
     * @return
     */
    public String payment_Global_FallbackMethod() {
        return "Global异常处理信息,请稍后再试,/(ㄒoㄒ)/~~";
    }
}
  • 解决耦合问题

  上述操作中,原方案和兜底方案都在controller中定义,想要解决这个耦合问题可以使用一个类实现service接口,然后重写所有的接口方法,然后使用service接口上@FeignClient注解的fallback属性指定接口的实现类为兜底类

@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT", fallback = PaymentFallbackService.class)
public interface PaymentHystrixService {
    @GetMapping("/payment/hystrix/ok/{id}")
    String paymentInfoOK(@PathVariable("id") Integer id);
    @GetMapping("/payment/hystrix/timeout/{id}")
    String paymentInfoTimeOut(@PathVariable("id") Integer id);
    @GetMapping("/payment/hystrix/ex/{id}")
    String paymentInfoException(Integer id);
}
@Component
public class PaymentFallbackService implements PaymentHystrixService {
    @Override
    public String paymentInfoOK(Integer id) {
        return "-----PaymentFallbackService fall back-paymentInfo_OK ,o(╥﹏╥)o";
    }
    @Override
    public String paymentInfoTimeOut(Integer id) {
        return "-----PaymentFallbackService fall back-paymentInfo_TimeOut ,o(╥﹏╥)o";
    }
    @Override
    public String paymentInfoException(Integer id) {
        return "-----PaymentFallbackService fall back-paymentInfoException ,o(╥﹏╥)o";
    }
}

服务熔断(break)

break是什么

  微服务链路中某个微服务的请求达到最大访问之后,直接拒绝访问,然后调用服务降级的方法返回友好的提示;当检测到该节点微服务调用响应正常之后,还可以恢复链路的正常调用。hystrix会默认在服务5秒内调用失败20次后触发熔断机制,但是也可以使用配置对其进行修改。

服务提供方实现服务熔断

  首先service层使用注解配置服务熔断的相关值和熔断时的备选方案,就以下代码为例:在10S的时间窗口期中,10次请求中失败率达到60%就会触发熔断启动备选方案。

  如果在10S的时间窗口期中,请求次数不足10次,那么根本就不可能触发熔断器。当熔断器开启后所有的请求都不会被转发,一段时间窗口期之后(默认5秒,可以自定义配置)断路器切换为半开状态,此时会让其中一个请求进行转发,成功则关闭断路器,反之继续开启

@HystrixCommand(fallbackMethod = "paymentCircuitBreakerFallback", 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(Integer id) {
    if (id < 0) {
        throw new RuntimeException("******id 不能负数");
    }
    String serialNumber = IdUtil.simpleUUID();
    return Thread.currentThread().getName()   "\t"   "调用成功,流水号: "   serialNumber;
}
public String paymentCircuitBreakerFallback(Integer id) {
    return Thread.currentThread().getName()   "\t"   "id 不能负数或超时或自身错误,请稍后再试,/(ㄒoㄒ)/~~   id: "   id;
}

  controller中调用service方法

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

服务限流(flowlimit)

flowlimit是什么

  在秒杀等高并发的操作下,为了防止大量请求一块发送过来,采用排队的方式,把请求按照顺序排队发送过来。由于hystrix已经停止更新,而且Alibaba的sentinel在进行服务限流的处理时比hystrix更加优秀,所以说这一部分知识可以放在后面进行学习。

Hystrix图形化监控

  第一步: 新建一个模块用于监控,导入相关依赖

<dependencies>
	<!--最主要的依赖,用于引入图形化dashboard-->
    <dependency>
        <groupId>org.springframework.cloud</groupId>
        <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
    </dependency>
    <!-- 引入自己定义的api通用包 -->
    <dependency>
        <groupId>com.xiaochen</groupId>
        <artifactId>cloud-api-commons</artifactId>
        <version>${project.version}</version>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>org.projectlombok</groupId>
        <artifactId>lombok</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-actuator</artifactId>
    </dependency>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-test</artifactId>
        <scope>test</scope>
    </dependency>
</dependencies>

  第一步: 配置文件配置端口号

server:
  port: 9001

  第三步: 主启动类开启HystrixDashboard,

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

  此外,所有的服务提供方也就是被监控的服务都要引入spring-boot-starter-actuator依赖,表示自己可以受监控。然后就是在服务的主启动类上要使用以下代码中的addUrlMappings配置受监控的路径

/**
 * 注意:新版本Hystrix需要在主启动类中指定监控路径
 * 此配置是为了服务监控而配置,与服务容错本身无关,spring cloud升级后的坑
 * ServletRegistrationBean因为springboot的默认路径不是"/hystrix.stream",
 * 只要在自己的项目里配置上下面的servlet就可以了
 *
 * @return ServletRegistrationBean
 */
@Bean
public ServletRegistrationBean getServlet() {
    HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
    ServletRegistrationBean registrationBean = new ServletRegistrationBean(streamServlet);
    // 一启动就加载
    registrationBean.setLoadOnStartup(1);
    // 添加url
    registrationBean.addUrlMappings("/hystrix.stream");
    // 设置名称
    registrationBean.setName("HystrixMetricsStreamServlet");
    return registrationBean;
}

  启动监控模块、eureka模块、受监控模块之后,访问以下路径可以通过路径监控指定的服务,设置后点击下面的Monitor Stream按钮即可进入图形化监控界面

图形化界面各处代表的含义如下:

到此这篇关于SpringCloud hystrix服务降级概念介绍的文章就介绍到这了,更多相关SpringCloud hystrix内容请搜索Devmax以前的文章或继续浏览下面的相关文章希望大家以后多多支持Devmax!

SpringCloud hystrix服务降级概念介绍的更多相关文章

  1. SpringCloud超详细讲解微服务网关Zuul基础

    这篇文章主要介绍了SpringCloud Zuul微服务网关,负载均衡,熔断和限流,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  2. SpringCloud gateway+zookeeper实现网关路由的详细搭建

    这篇文章主要介绍了SpringCloud gateway+zookeeper实现网关路由,本文通过图文实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下

  3. SpringCloud OpenFeign 服务调用传递 token的场景分析

    这篇文章主要介绍了SpringCloud OpenFeign 服务调用传递 token的场景分析,本篇文章简单介绍 OpenFeign 调用传递 header ,以及多线程环境下可能会出现的问题,其中涉及到 ThreadLocal 的相关知识,需要的朋友可以参考下

  4. Springcloud Stream消息驱动工具使用介绍

    SpringCloud Stream由一个中间件中立的核组成,应用通过SpringCloud Stream插入的input(相当于消费者consumer,它是从队列中接收消息的)和output(相当于生产者producer,它是发送消息到队列中的)通道与外界交流

  5. SpringCloud中Gateway的使用教程详解

    SpringCloud Gateway是Spring体系内的一个全新项目,它旨在为微服务架构提供一种简单有效的统一的API路由管理方式。本文就来为大家详细讲讲Gateway的使用教程,需要的可以参考一下

  6. SpringCloud 客户端Ribbon负载均衡的实现方法

    Ribbon 是 Netflix 提供的一个基于 Http 和 TCP 的客户端负载均衡工具,且已集成在 Eureka 依赖中,这篇文章主要介绍了SpringCloud 客户端Ribbon负载均衡的实现方法,需要的朋友可以参考下

  7. SpringCloud服务网关Gateway的使用教程详解

    SpringCloud Gateway是Spring体系内的一个全新项目,它旨在为微服务架构提供一种简单有效的统一的API路由管理方式。本文就来为大家详细讲讲Gateway的使用教程,需要的可以参考一下

  8. SpringCloud 分布式微服务架构操作步骤

    SpringCloud是一种微服务的框架,利用它我们可以去做分布式服务开发,这篇文章主要介绍了SpringCloud 分布式微服务架构,需要的朋友可以参考下

  9. SpringCloud迈向云原生的步骤

    这篇文章主要介绍了SpringCloud怎么迈向云原生,通过本文我们来梳理一下Spring Cloud的前世今生,以及未来云原生发展的趋势,可以给这些RPC框架的演进带来一些启发,感兴趣的朋友跟随小编一起看看吧

  10. Spring Cloud Alibaba微服务组件Sentinel实现熔断限流

    这篇文章主要为大家介绍了Spring Cloud Alibaba微服务组件Sentinel实现熔断限流过程示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部