SpringCloud学习(五)—— Hystrix 断路器

Hystrix

前言

分布式系统面临的问题:

多个微服务之间调用时,如果扇出的链路上某个微服务的调用时间过长或者不可用,对于这个微服务的调用就会占用越来越多的系统资源,导致系统发生更多的级联故障,进而引起系统崩溃,发生所谓的“雪崩效应”。
因此需要对故障和延迟进行管理和隔离,以便当个依赖关系的失败,不会影响整个应用程序或 系统。这也是Hystrix的来源。

什么是Hystrix

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

Hystrix的做法是: 当某个单元发生故障之后,通过断路器的故障监控,向调用方法返回一个符合预期的、可处理的备选方案,而不是长时间的等待或者抛出调用方无法处理的异常,这样就保证了服务调用方的线程不会被长时间的占用,从而避免了故障在 分布式系统的蔓延,内置雪崩。

一些概念

服务降级

服务器忙,请稍后再试,不让客户端等待并返回一个友好提示fallback
哪些情况会 发生降级

  1. 程序运行异常
  2. 超时
  3. 服务熔断触发服务降级
  4. 线程池/信号量打满也会导致服务降级

服务熔断

达到最大服务访问后,直接拒绝访问,然后调用服务降级方法并返回友好 提示。相当于保险丝,在家用电器超负荷时,拉闸限电。

服务限流

秒杀高并发等操作,严禁一窝蜂的过来拥挤,大家排队,一秒钟N个,有序进行。

在这里插入图片描述

代码演示

模拟故障

使用jemeter发起200万个请求http://localhost:8001/payment/hystrix/timeout/35
1个请求http://localhost:8001/payment/hystrix/ok/35,会发现后者也会 被滞缓。
原因是:
SpringBoot集成tomcat,而tomcat默认的工作线程被打满了,没有多余的线程来分解压力和处理 。因为有上述故障或不佳表现,才有了我们的降级/容错/限流等技术的诞生。

解决思路

  1. 对于超时 导致服务器变慢(访问转圈)应该设置超时不再等待
  2. 出错(宕机 或程序运行错误),出错要有兜底

解决方案:

服务提供方(8001)超时了,调用者(80) 不能一直卡死等待,必须要有服务降级
服务提供方(8001)宕机了,调用者(80)不能一直卡死等待,必须要有服务降级。
服务提供方(8001)OK,调用者(80)自己出故障或有自我要求(自己等待时间小于服务提供方的业务所需时间),自己降级处理。

服务降级

8001demo
引入Hystrix依赖spring-cloud-starter-netflix-hystrix

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

主启动类加入注解@EnableCircuitBreaker,服务降级

Service层

@HystrixCommand(fallbackMethod = "兜底的方法",commandProperties = {
            @HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="5000")
    })

eureka自带负载均衡ribbon

在这里插入图片描述

配置过的热部署方式对Java代码的改动明显有效,但对于@HystrixCommand内属性的修改建议重启微服务。

服务降级客户端和服务端都可以设置,但是一般放置在客户端

客户端处配置服务降级

application.yaml文件

feign:
	hystrix:
		enabled: true

主启动类增加@EnableHystrix注解、@EnableFeignClients注解

超时设置:
@HystrixProperty注入的超时时间和application.yml注入的超时时间都处于生效状态, 哪边的时间小超时时间就取哪边. 当application.yml 未设置Hystrix的超时时间时, 会有个默认的超时时间1秒, 设置了application.yml的Hystrix超时时间后会覆盖掉1秒超时的默认设置.

Feign的超时时间为:Hystrix + Ribbon的
Ribbon 的超时时间(ReadTimeOut + ConnectionTimeOut)
图源关于客户端feign readTimeout设置

存在的问题:

  1. 每个方法都要配置一个fallbackMethod的代码膨胀问题 —— 全局服务降级解决
  2. 异常处理 代码与业务逻辑混在一起的耦合问题。 —— 服务类实现接口

全局服务降级

在这里插入图片描述

  1. 在需要使用服务降级的方法上加上@HystrixCommand注解
  2. 在Controller上加上@DefaultProperties(defaultFallback = “全局降级方法”)
  3. 定义全局降级方法
package com.johnny.springcloud.controller;

import com.johnny.springcloud.service.PaymentService;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import com.netflix.ribbon.proxy.annotation.Hystrix;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

/**
 * @author Johnny Lin
 * @date 2021/6/25 14:45
 */

@RestController
@Slf4j
@RequestMapping("consumer/payment")
@DefaultProperties(defaultFallback = "globalFallback_Method") //开启全局fallback
public class OrderController {

    @Autowired
    private PaymentService paymentService;

    @GetMapping("/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id){
        return paymentService.paymentInfo_OK(id);
    }
    //hystrix.command.serverMethod.execution.isolation.thread.timeoutInMilliseconds=3000
    @GetMapping("/hystrix/timeout/{id}")
//    @HystrixCommand(fallbackMethod = "paymentTimeoutFallbackMethod",commandProperties =
//            {@HystrixProperty(name="execution.isolation.thread.timeoutInMilliseconds",value="30000") } )
    @HystrixCommand
    public String paymentInfo_Timeout(@PathVariable("id") Integer id){
        int a = 25 / 0;     //处理异常
        return paymentService.paymentInfo_Timeout(id);
    }
    public String paymentTimeoutFallbackMethod(@PathVariable("id") Integer id){
        return "消费者端80, 支付系统繁忙请10秒钟之后再试或者自己运行出错请检查自己 2222  o(╥﹏╥)o";
    }
    //不是globalFallback_Method(@PathVariable("id") Integer id)
    public String globalFallback_Method(){
        return "全局服务降级处理方法  globalFallback_Method";
    }
}


解决代码耦合问题

80客户端:

PaymentService 接口

package com.johnny.springcloud.service;

import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;

/**
 * @author Johnny Lin
 * @date 2021/6/25 14:26
 */
@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT", fallback = PaymentFallbackService.class)  //要调用的服务端名称
public interface PaymentService {
    @GetMapping("payment/hystrix/ok/{id}")
    String paymentInfo_OK(@PathVariable("id") Integer id);

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

package com.johnny.springcloud.service;

import org.springframework.stereotype.Component;

/**
 * @author Johnny Lin
 * @date 2021/6/26 10:23
 */
//还要加上component注解
@Component
public class PaymentFallbackService implements PaymentService {
    @Override
    public String paymentInfo_OK(Integer id) {
        return "paymentInfo_OK invoke o(╥﹏╥)o ~~";
    }

    @Override
    public String paymentInfo_Timeout(Integer id) {
        return "paymentInfo_Timeout invoke o(╥﹏╥)o ~~";
    }
}

关闭服务端8001,启动80访问

http://localhost/consumer/payment/hystrix/timeout/99

结果:

在这里插入图片描述

实现类是针对异常情况(服务器宕机、超时、运行时异常)的fallback处理,是客户端的降级方案。
接口才是服务端的映射,对应服务端的具体逻辑业务。

熔断

熔断机制

熔断机制是应对雪崩效应的一种微服务链路保护机制。当扇出链路的某个微服务出错不可用或者 响应时间过长时,会进行服务的降级,进而熔断该节点微服务的调用,快速返回错误的响应信息。
当检测到该节点微服务调用响应正常后,恢复调用链路。
在这里插入图片描述

在这里插入图片描述

熔断类型

熔断打开: 请求不再进行调用当前服务,内部设置时钟一般为MTTR(平均故障处理时间),当打开时长达到所设时钟则进入半熔断状态
熔断关闭: 熔断关闭不会对服务进行熔断
熔断半开: 部分请求根据规则调用当前服务,如果请求成功且符合规则则认为当前服务恢复正常,关闭熔断。

断路器在什么情况下起作用

在这里插入图片描述
在这里插入图片描述

断路器打开之后

在这里插入图片描述

Hystrix的工作流程

Hystrix Dashboard

除了隔离依赖服务的调用以外,Hystrix还提供了准实时的调用监控(Hystrix Dashboard),Hystrix会 持续地记录所有通过Hystrix发起的请求执行信息,并以统计报表和图形的形式展示给用户。

pom.xml引入依赖

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

主启动类增加注解

@EnableHystrixDashboard

压力测试

关于客户端feign readTimeout设置

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值