分布式微服务学习总结——Hystrix


一、前言

最近刚看完springcloud、dubbo的学习视频,但感觉不是那么扎实,所以打算写一个系列的博客来巩固自身所学。
当然有些内容是参考了别的博客,毕竟我也是初探分布式微服务的,并不是所谓的大神,只是一个新手在初探分布式微服务后写下的一些自己的理解和总结。


注:以下简述部分来自官方文档翻译(官方文档写的已经很好了,所以直接搬运)

官方文档地址:https://github.com/Netflix/hystrix/wiki

二、简述

什么是 Hystrix?

在分布式环境中,不可避免地会遇到所依赖的服务挂掉的情况,Hystrix 可以通过增加 延迟容忍度 与 错误容忍度,来控制这些分布式系统的交互。Hystrix 在服务与服务之间建立了一个中间层,防止服务之间出现故障,并提供了失败时的 fallback 策略,来增加你系统的整体可靠性和弹性。

Hystrix 做了那些事情?

Hystrix 提供了以下服务

引入第三方的 client 类库,通过延迟与失败的检测,来保护服务与服务之间的调用(网络间调用最为典型)
阻止复杂的分布式系统中出现级联故障
快速失败与快速恢复机制
提供兜底方案(fallback)并在适当的时机优雅降级
提供实时监控、报警与操作控制

Hystrix 解决了什么问题?

在复杂的分布式架构中,服务之间都是相互依赖的,任何一个节点都不可避免会宕机。如果主节点不能从这些宕机节点中独立出来,那主节点将会面临被这些宕机的节点拖垮的风险。举个例子,如果一个应用依赖了 30 个服务,每个服务保证 99.99% 的时间是正常的,那可以计算出

99.9930 = 99.7% uptime
0.3% of 1 billion requests = 3,000,000 failures
2+ hours downtime/month even if all dependencies have excellent uptime.

实际情况往往更糟糕

完好情况下,请求流如下:
在这里插入图片描述

当一个依赖的节点坏掉时,将阻塞整个的用户请求:
在这里插入图片描述

流量高峰时,一个单节点的宕机或延迟,会迅速导致所有服务负载达到饱和。应用中任何一个可能通过网络访问其他服务的节点,都有可能成为造成潜在故障的来源。更严重的是,还可能导致服务之间的延迟增加,占用队列、线程等系统资源,从而导致多系统之间的级联故障。
在这里插入图片描述

更严重的是,当网络请求是通过第三方的一个黑盒客户端来发起时,实现细节都被隐藏起来了,而且还可能频繁变动,这样发生问题时就很难监控和改动。如果这个第三方还是通过传递依赖的,主应用程序中根本没有显示地写出调用的代码,那就更难了。

网络连接失败或者有延迟,服务将会产生故障或者响应变慢,最终反应成为一个 bug。

所有上述表现出来的故障或延迟,都需要一套管理机制,将节点变得相对独立,这样任何一个单节点故障,都至少不会拖垮整个系统的可用性。

Hystrix 的设计原则是什么?

Hystrix 通过以下设计原则来运作:

防止任何一个单节点将容器中的所有线程都占满
通过快速失败,取代放在队列中等待
提供在故障时的应急方法(fallback)
使用隔离技术 (如 bulkhead, swimlane, 和 circuit breaker patterns) 来限制任何一个依赖项的影响面
提供实时监控、报警等手段
提供低延迟的配置变更
防止客户端执行失败,不仅仅是执行网络请求的客户端

Hystrix 如何时间它的目标?

如下:

将远程请求或简单的方法调用包装成 HystrixCommand 或者 HystrixObservableCommand 对象,启动一个单独的线程来运行。
你可以为服务调用定义一个超时时间,可以为默认值,或者你自定义设置该属性,使得99.5%的请求时间都在该时间以下。
为每一个依赖的服务都分配一个线程池,当该线程池满了之后,直接拒绝,这样就防止某一个依赖的服务出问题阻塞了整个系统的其他服务
记录成功数、失败数、超时数以及拒绝数等指标
设置一个熔断器,将所有请求在一段时间内打到这个熔断器提供的方法上,触发条件可以是手动的,也可以根据失败率自动调整。
实时监控配置与属性的变更

当你启用 Hystrix 封装了原有的远程调用请求后,整个流程图变为下图所示。
在这里插入图片描述

接下来让我们学习如何使用它吧

三、快速入门

注解方式

此种方式最为简便,适用于大部分情况,但无法进行动态配置

1.导入依赖(服务提供者端)

		<!--熔断机制-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>
        <!--完善监控信息-->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
        </dependency>

2.在需要添加熔断机制的类上加上fallback方法并进行注解(服务提供者端)

如下:

package com.dreamchaser.springcloud.controller;

import com.dreamchaser.pojo.Tag;
import com.dreamchaser.springcloud.service.TagService;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

@Controller
public class TagController {
    
    
    @Autowired
    TagService tagService;

    @GetMapping(value = "/tag",produces = "application/json;charset=UTF-8")
    //添加熔断注解
    @HystrixCommand(fallbackMethod = "hystrixGet")
    public @ResponseBody List<Tag> findTags(){
    
    
        List<Tag> list=tagService.findTagAll();
        if (list==null){
    
    
            throw new RuntimeException("不存在该标签,id未找到!");
        }
        list.get(0).setId(8005);
        return list;
    }

    @PostMapping("/tag")
    @HystrixCommand(fallbackMethod = "hystrixGet")
    public @ResponseBody String insertTag(Tag tag){
    
    
        if (tagService.insertTag(tag)==1){
    
    
            return "添加新标签成功!";
        }else {
    
    
            return "添加新标签失败!";
        }
    }

    //备选方案
    public @ResponseBody List<Tag> hystrixGet(){
    
    
        Tag tag=new Tag();
        tag.setId(1).setName("没有对应的信息!").setDate(new Date()).setNumber(0);
        List<Tag> list=new ArrayList<>();
        list.add(tag);
        return list;

    }

}

需要自己写个fallback方法,并且在需要加熔断机制的方法上加上@HystrixCommand(fallbackMethod = “hystrixGet”)注解,fallbackmethod表示回调的方法。

即当服务发生超时、异常或者线程已满等服务不可用的情况时,hystrix会记录,并直接执行fallback方法。当服务健康状况达到一定程度,会触发服务降级。

服务的健康状况=请求失败数/请求总数

3.开启熔断支持(服务提供者端)

在启动类上加上@EnableCircuitBreaker注解来开启熔断支持。

至此我们便已经开启了熔断机制,如果还想进行流量监控则还需以下几步。

4.注册一个servlet来作为检测地址(服务提供者端)

可以在启动类中加入一个方法

//增加一个servlet
    @Bean
    public ServletRegistrationBean hystrixMetricsStreamServlet(){
    
    
        ServletRegistrationBean registrationBean=new ServletRegistrationBean(new HystrixMetricsStreamServlet());
        registrationBean.addUrlMappings("/actuator/hystrix.stream");
        registrationBean.setLoadOnStartup(1);
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }

这表示在项目中加上一个servlet,这样访问该地址时会返回一个stream流,用来hystrix对服务进行流监控。

5.加入依赖并开启流监控(服务消费者端)

添加依赖

		<!--dashboard流监控-->
        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.cloud</groupId>
            <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
        </dependency>

开启流监控

@EnableHystrixDashboard

6.测试运行

启动完进程,打开http://localhost:81/hystrix(就是消费端地址后加上hystrix)

在这里插入图片描述

我们看到了一只豪猪。。。

访问一下业务

正常!

在这里插入图片描述
访问我们刚设置的servlet地址

在这里插入图片描述

可以看到它每隔一秒发送一段字符串

把这个地址输入hystrix页面

输入地址后点击右下角的按钮,我们可以看到这样一个画面

在这里插入图片描述

绿色表示服务访问成功的次数,每次刷新业务的接口地址,上面的数字就会+1。

这样就相当于与仪表盘一样来监测服务的实时状态,达到实时监控的效果。

如果想要更加详细的配置,具体可以参考这篇文章Hystrix在项目中的使用(一)-注解方式

命令式编程方式

这种方式就比较麻烦了,对代码的修改程度就比较大,一般不建议采用,不过它可以实现动态配置,如果实在要用可采用aop切面来减少对代码的影响。

具体可以参考这篇Hystrix在项目中的使用(二)-基于AOP实现命令式编程(动态配置)

四、总结

hystrix是一款功能强大的中间件,用来解决某个服务节点宕机导致服务雪崩的问题。

同时还可以用来实时监控服务的流量情况。


如果随着我的学习发现自己所写的有所纰漏或者错误,我会第一时间来修正博客,当然如果有什么错误,欢迎大家评论区评论指正,不胜感激。

愿我们都能以梦为马,不负人生韶华!
以此为记,与君共勉!


猜你喜欢

转载自blog.csdn.net/qq_46101869/article/details/108196053