SpringCloud系列-Hystrix 微服务容错保护

SpringCloud系列-Hystrix 微服务容错保护

        SpringCloud Hystrix实现了断路器、线程隔离等一系列服务保护功能。它也是基于Netflix的开源框架Hystrix实现的,该框架的目标在于通过控制那些访问远程系统、服务和第三方库的节点,从而对延迟和故障提供更强大的容错能力。Hystrix具备服务降级、服务熔断、线程和信号隔离、请求缓存、请求合并以及服务监控等强大功能。

服务调用关系图:
在这里插入图片描述
        在学习Hystrix之前,我们先来了解一下容错及容错的手段。
        前面介绍了Eureka与Ribbon之后,我们了解了服务提供者、服务消费者、注册中心之间的关系,如果服务提供者响应非常缓慢,那么消费者对提供者的请求就会被强制等待,直到提供者响应超时。在高负载场景下,如果不做任何处理,此类问题可能会导致服务消费者的资源耗竭甚至整个系统的崩溃。

雪崩效应

微服务架构的应用系统通常包含多个服务层。微服务之间通过网络进行通信,从而支撑起整个应用系统,因此,微服务之间难免存在依赖关系。现实场景中,我们常把“基础服务故障“导致“级联故障”的现象称为雪崩效应。雪崩效应描述的是提供者不可用导致消费者不可用,并将不可用逐渐放大的过程。

如何容错

要想防止雪崩效应,必须有一个强大的容错机制。该容错机制需要实现以下两点。

  • 为网络请求设置超时
    通常情况下,一次远程调用对应着一个线程/进程。如果响应太慢,这个线程、进程就得不到释放。而线程/进程又对应着系统资源,如果得不到释放的线程/进程月积越多,资源就会被逐渐被耗尽,最终导致服务的不可用。
    因此,必须为每个网络请求设置超时,让资源尽快释放。
  • 使用断路器模式
    如果某个微服务的请求有大量超时,再去让新的请求访问该服务已经没有任何意义,只会无畏消耗资源。
    断路器可理解为对容易导致错误的操作的代理。这种代理能够统计一段时间内调用失败的次数,并决定是正常请求依赖的服务还是直接返回。
    断路器可以实现快速失败,如果它在一段时间类检测到许多类似的错误,就会在之后的一段时间内,强迫对该服务的调用快速失败,即不在请求所依赖的服务。这样,应用程序就无须在浪费CPU时间去等待长时间的超时。
    断路器也可自动诊断依赖的服务是否已经恢复正常。如果发现依赖的服务已经恢复正常,那么就会恢复请求该服务。使用这种方式,就可以实现微服务的“自我修复“——当依赖的服务不正常是打开断路器时快速失败,从而防止雪崩效应;当发现依赖的服务恢复正常时,又会恢复请求。在这里插入图片描述
Hystrix简介

Hystrix是由Netflix开源的一个延迟和容错库,用于隔离访问远程系统、服务或第三方库,防止级联失败,从而提神系统的可用性与容错性。Hystrix主要通过以下几点实现延迟和容错。

  • 包裹请求:
    使用HystrixCommand(或HystrixObservableCommand)包裹对依赖的调用逻辑,每个命令在独立线程中执行。这使用到了设计模式中的“命令模式”。
  • 跳闸机制:
    当某服务的错误率超过一定阈值时,Hystrix可以自动或者手动跳闸,停止请求该服务的一段时间。
  • 资源隔离
    Hystrix为每个依赖都维护了一个小型的线程池(或者信号量)。如果该线程已满,发往该依赖的请求就被立即拒绝,而不是排队等候,从而加速失败判定。
  • 监控:
  • Hystrix可近乎实时地监控运行指标和配置的变化,例如成功、失败、超时以及被拒绝的请求等
  • 回退机制:
    当请求失败、超时、被拒绝,或当断路器打开时,执行回退逻辑。回退逻辑可由开发人员自行提供,例如返回一个缺省值。
  • 自我修复:
  • 断路器打开一段时间后,会自动进入“半开”状态。断路器打开、关闭、半开的逻辑转换
Hypstrix 设计原则:
  • 防止单个依赖耗尽所有容器用户线程
  • 提供降级服务,以保护用户请求失败
  • 使用隔离技术,阻断一个依赖故障的传播
  • 近实时的指标、监控
Hystrix 设计原理
  • 对外部系统或者依赖的调用都封装在HystrixCommand 或者HystrixObservableCommand
    对象中,该对象通常单独的在一个线程中执行
  • 可自定义设置服务调用超时时间
  • 为每一个依赖调用维护一个小线程池,如果它满了,则调用会被拒绝,而不是排队阻塞
快速开始

准备工作
在之前的章节当中,我们都搭建了以下的模块:

注册中心Eureka

服务提供者server-provider

服务调用者server-consumer
引入Hystrix

        我们在服务调用者server-consumer引入hystrix依赖,并且改造原来的服务调用接口:

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

        Fegin的调用接口HelloApi:

@FeignClient(name = "server-provider",configuration = MyFeignConfig.class)
public interface HelloApi {
    @RequestMapping("/sayHello")
    public String sayHello(@RequestParam("name") String name);
}

        新建控制器HystrixController,注入Feign接口,调用服务提供者,添加 @HystrixCommand注解,当服务调用失败时,我们通过fallbackMethod指定失败后调用的本地的方法名称,注意参数必须带上:

@RestController
@RequestMapping("/hystrix")
public class HystrixController {
    @Autowired
    HelloApi helloApi;

    @RequestMapping("/sayHello")
    @HystrixCommand(fallbackMethod = "sayError")
    public String sayHello(String name) {
        return helloApi.sayHello(name);
    }

    public String sayError(String name){
        return "sayError!";
    }

        服务提供端server-provider改造,让接口有一般的几率调用失败:

@RestController
public class RibbonController {
    @Value("${server.port}")
    private String port;

    @RequestMapping("/sayHello")
    public String sayHello(String name) {
        Random random = new Random();
        if (random.nextInt(10) < 5) {
            throw new RuntimeException("erroe");
        }
        return "from:" + port + ",hello!," + name;
    }

        接下来我们启动Eureka注册中心,两个服务提供者,一个服务调用者:
在这里插入图片描述
        使用浏览器调用接口:http://localhost:5168/hystrix/sayHello?name=name,有一半的几率是返回"sayError!":在这里插入图片描述
        这样就简单的实现了熔断、降级的功能。

        注意:上一章我们整合了Feign和Hystrix,Feign在配置的时候我们可以指定@FeignClient注解中的fallback,从这里我们可以看出来,Feign默认是集成了Hystrix的。如果我们同时配置了Feign的fallback,同时也配置了 @HystrixCommand(fallbackMethod = “sayError”),那么Feign的配置优先。

Hystrix更多配置

        我们可以在@HystrixCommand注解中添加属性,自定义配置,通过查看@HystrixCommand注解的源代码,
我们可以配置

  • commandProperties: 指令属性
  • threadPoolProperties:线程池的属性

等等,例如:


```bash
@RestController
@RequestMapping("/hystrix")
public class HystrixController {

    @Autowired
    HelloApi helloApi;

    @RequestMapping("/sayHello")
    @HystrixCommand(
            commandProperties = {
                    @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "500"),
                     @HystrixProperty(name = "execution.timeout.enabled", value = "false")
            },
            threadPoolProperties = {
                    @HystrixProperty(name = "coreSize", value = "30"),
                    @HystrixProperty(name = "maxQueueSize", value = "101"),
                    @HystrixProperty(name = "keepAliveTimeMinutes", value = "2"),
                    @HystrixProperty(name = "queueSizeRejectionThreshold", value = "15"),
                    @HystrixProperty(name = "metrics.rollingStats.timeInMilliseconds", value = "1440")
            },
            fallbackMethod = "sayError")
    public String sayHello(String name) {
        return helloApi.sayHello(name);
    }
    public String sayError(String name) {
        return "sayError!";
    }
}
  • execution.isolation.thread.timeoutInMilliseconds
    :设置thread和semaphore两种策略的超时时间,默认是1000毫秒,这也是我们写程序经常忽略的一点,命名接口没错,但是调用就是失败,这里我们可以设置超时时长。
  • execution.timeout.enabled:是否开启超时,默认是true
  • execution.isolation.thread.interruptOnTimeout:发生超时时,是否中断线程,默认true
  • circuitBreaker.sleepWindowInMilliseconds:熔断后多久开始尝试恢复
  • circuitBreaker.errorThresholdPercentage:出错百分比阈值,默认是50%

        当然我们也可以配置在yml配置文件中:通过hystrix.command.[commandKey],commandKey 默认是default,对于Zull而言就是 service ID:

 hystrix: 
   command:
       default:
         execution:
           timeout:
             enabled : false

        当服务端因为网络延迟或故障出险问题时,我们可以通过Hystrix实现服务熔断,那么如何做到迅速的发现问题并且迅速的解决问题呢?熔断的监控工具有2款工具:Hystrix-dashboard和Turbine,Hystrix-dashboard是针对Hystrix进行实时的监控工具,通过Hystrix-dashboard我们可以直观的看到单个应用的服务信息。但是,在分布式的模式下,我们需要一个能够汇总所有的服务数据并直观的显示出来,这个工具就是Turbine。’

        Eureka是默认使用心跳机制来监测服务的健康与否的,我们通过在服务端引入actuator依赖,并修改yml配置,开启健康检查,能够查到服务是否正常,这里在需要被监测的服务组件中,开启监控也需要引入actuator:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-actuator</artifactId>
</dependency>

application.yml 添加配置,默认只有"health",“info”,这里我们添加"hystrix.stream":

management:
  endpoints:
    web:
      exposure:
         include: ["health","info","hystrix.stream"]

        在被检测的项目中引入actuator就可以通过接口的方式收集Hystrix Command标注的资源接口参数信息,我们还可以通过直观的方式,使用Hystrix-dashboard仪表盘的方式展示:
         首先,新建仪表盘应用Monitor,创建Maven项目,引入hystrix-dashboard依赖:

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

在主类上添加@EnableHystrixDashboard注解,表示开启仪表盘:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.netflix.hystrix.dashboard.EnableHystrixDashboard;

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

访问http://localhost:8412/hystrix访问仪表盘的页面:
在这里插入图片描述        控制主页面,我们可以输入指定服务的接口,刷新时间,默认是2秒就可以显示指定服务的监控数据了,比如我们可以输入server-consumer服务消费者的url http://localhost:5168/actuator/hystrix.stream ,就可以实时的显示以下的信息:
在这里插入图片描述
具体的信息,包括了成功数量、熔断数量,错误数量,错误的百分比等等信息:
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值