分布式微服务学习总结——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是一款功能强大的中间件,用来解决某个服务节点宕机导致服务雪崩的问题。

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


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

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


全部评论

相关推荐

有很多问题,求大佬们解答,谢谢大佬们:不知道现在该怎么投实习,该怎么准备内心很纠结学校课程和实习到底怎么选择,&nbsp;自己也不想课程学业这边出问题,&nbsp;是不是只能投暑期实习,具体时间该怎么安排前端面试也需要准备算法么,&nbsp;自己的算法能力很薄弱,&nbsp;面试题需要准备到什么程度?没有ai项目经验的话,我该如何去补充,如何去找好的ai项目
smile丶snow:1.简历尽量一页,比如教育经历那里,全日制,计算机学院这些可以去掉没啥用好浪费空间。 熟悉三件套就没必要写了吧。js基本上是这样写 * JavaScript核心:深入理解 JS 运行机制(事件循环 Event Loop、微任务/宏任务),熟练掌握 Promise/Async 异步编程 模型。 熟悉可以改成熟练掌握。组件库写一个ant感觉就行,多写了浪费空间。 旅游项目是不是jonas的natours啊,我之前简历也有这个。我之前是这样写的 全栈思维: 熟悉 Node.js/Express 后端架构,掌握 MongoDB 数据库设计与聚合查询 工程化我觉得还是少些吧,不写就问的少,如果你真的了解的话可以写。 1.实习的话推荐大厂官网和aoob上面投,我自己有写一个校招网站的小网站可以直达~github主页上面有,顺便求个关注( 2.大三下一般课程比较少了吧,如果学校比较严的话可以多沉淀一会,如果不太严可以请dai课然后去实习,尽量找个近一些的就行。暑期实习不是暑假才实习哦,基本是上3月底4月初发offer就可以过去了,然后大概暑假的时候走转正流程答辩。 3.大厂算法题+js手写体。hot100+常见的比如数组转树,Promise.all,deepClone,之类 js手写都不难其实。算法看自己能力吧,我其实算法能力也不行。 4.自己平时没有用AI Coding吗?自己想一下怎么让AI帮你更好的写代码~比如Skill的诞生,OpenSpec的诞生,不都是我们想让AI更好帮我们写代码吗。
我的实习日记
点赞 评论 收藏
分享
03-06 18:20
门头沟学院 Java
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务