Hystrix

服务雪崩

1.雪崩过程

  • 若存在服务调用链
    在这里插入图片描述
  • 此时Service A流量波动很大,流量经常会突然性增加
  • 在这种情况下,就算Service A能扛得住请求,Service B和Service C未必能扛得住这突发的请求
    在这里插入图片描述
  • 若Service C因抗不住请求变得不可用,那么Service B的请求也会阻塞
  • 慢慢耗尽Service B的线程资源,Service B就会变得不可用
  • 紧接着,Service A也会不可用

2.概念

  • 一个服务失败导致整条链路的服务都失败的情形称为服务雪崩

3.雪崩三阶段

  • 服务不可用
硬件故障/程序Bug/缓存击穿/用户大量请求
  • 调用端重试加大流量
用户重试/代码逻辑重试
  • 服务调用者不可用
同步等待造成的资源耗尽

4.解决方案

  • 应用扩容
加机器/升级硬件
  • 流控
限流/关闭重试
  • 缓存预加载
  • 服务降级
服务接口拒绝服务/页面拒绝服务/延迟持久化/随机拒绝服务
  • 服务熔断

服务熔断

1.概念

  • 当下游服务因某种原因突然变得不可用或响应过慢,上游服务为保证自己整体服务的可用性,不再继续调用目标服务,直接返回,快速释放资源,如果目标服务情况好转则恢复调用

2.解决方案

  • 断路器模式

3.断路器模式

  • 原理
当远程服务被调用时,断路器将监视这个调用,如调用时间太长,断路器将会介入并中断调用。
断路器将监视所有远程资源的调用,如对某个远程资源的调用失败次数足够多,那么断路器会出现并采取快速失败,阻止将来调用失败的远程资源 
  • 状态图
    在这里插入图片描述
  • 解析
断路器最开始处于closed状态,一旦检测到的错误到达一定数量,断路器便转为open状态(断路器打开);
此时到达reset timeout时间会转移到half open状态;
尝试放行一部分请求到后端,一旦检测成功便回归到closed状态,即恢复服务
  • 实现
阿里的Sentinel
netflix的Hystrix
  • Hystrix常用配置
//滑动窗口的大小,默认为20
circuitBreaker.requestVolumeThreshold 
//过多长时间,熔断器再次检测是否开启,默认为5000,即5s钟
circuitBreaker.sleepWindowInMilliseconds 
//错误率,默认50%
circuitBreaker.errorThresholdPercentage

每当20个请求中,有50%失败时,熔断器就会打开,此时再调用此服务,将会直接返回失败,不再调远程服务。直到5s钟之后,重新检测该触发条件,判断是否把熔断器关闭,或者继续打开

服务降级

1.场景

  • 当下游服务因某种原因响应过慢,下游服务主动停掉一些不太重要的业务,释放出服务器资源,增加响应速度!
  • 当下游服务因某种原因不可用,上游主动调用本地的一些降级逻辑,避免卡顿,迅速返回给用户!

2.服务熔断可视为降级方式的一种

3.实际项目中的降级工作

  • 微服务下肯定有很多功能,需要自己区分出主要功能和次要功能(核心业务流程和非核心业务流程),梳理出核心业务流程和非核心业务流程后,在非核心业务流程上加上开关,一旦发现系统扛不住则关掉开关,结束次要流程
  • 降低一致性要求,将核心业务流程的同步改异步,强一致性改最终一致性

Hystrix

1.目标

  • 微服务架构是高度分布式的,必须防止单个服务(或服务实例)中的问题级联暴露给服务消费者

2.原理图

在这里插入图片描述

Hello断路器模式—消费端

1.HelloFeign基础之上进行配置,以下只出示改动部分,原理前面有讲过

2.修改microcloud-api下feign配置

  • 目录结构
    在这里插入图片描述
  • pom.xml
//feign含有Hystrix包
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  • 修改feign接口
@FeignClient(name = "MICROCLOUD-PROVIDER-DEPT", fallbackFactory = DeptFeignServiceFallbackFactory.class)
public interface DeptFeignService {

    @RequestMapping("/provider/addDept") //映射到服务提供方的地址
    public JsonModel addDept(@RequestBody Dept dept);

    @RequestMapping("/provider/findById/{id}")
    public JsonModel findById(@PathVariable("id") Long id);

    @RequestMapping("/provider/findAll")
    public JsonModel fingAll();
}
  • 添加DeptFeignServiceFallbackFactory
//feign接口调用的回退处理类
@Component
public class DeptFeignServiceFallbackFactory implements FallbackFactory<DeptFeignService> {
    @Override
    public DeptFeignService create(Throwable throwable) {
        return new DeptFeignService() {
            @Override
            public JsonModel addDept(Dept dept) {
                JsonModel jsonModel = new JsonModel();
                jsonModel.setCode(-1);
                jsonModel.setData("消费端端addDept不可用");
                return jsonModel;
            }

            @Override
            public JsonModel findById(Long id) {
                JsonModel jsonModel = new JsonModel();
                jsonModel.setCode(-1);
                jsonModel.setData("消费端端findById不可用");
                return jsonModel;
            }

            @Override
            public JsonModel fingAll() {
                JsonModel jsonModel = new JsonModel();
                jsonModel.setCode(-1);
                jsonModel.setData("消费端端fingAll不可用");
                return jsonModel;
            }
        };
    }
}

3.修改microcloud-consumer-dept-feign-80

  • 目录结构
    在这里插入图片描述
  • pom.xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
  • application.xml
feign:
  hystrix:
    enabled: true

Hello后备模式—提供端

1.新建模块microcloud-provider-dept-hystrix-8001

  • 为了与之前的provider分开

2.目录结构

在这里插入图片描述

3.pom.xml

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

4.修改controller下的DeptProviderServlet

@RestController
@RequestMapping("/provider")
public class DeptProviderServlet {
    @Autowired
    private DeptService deptService;

    @RequestMapping("/findAll")
    @HystrixCommand(fallbackMethod = "getMethodCallback")//后备方法名,必须是当前类中某方法名
    //当Hystrix检测请求长时间没有响应时,执行fallbackMethod绑定的当前类同方法名的方法
    public JsonModel fingAll(JsonModel jsonModel) {
        List<Dept> list = this.deptService.fingAll();
        jsonModel.setCode(1);
        jsonModel.setData(list);
        return jsonModel;
    }

    //后备模式时回调的方法
    public JsonModel getMethodCallback(JsonModel jsonModel) {
        //服务降级
        jsonModel.setCode(-1);
        jsonModel.setData("服务降级,服务查找缓慢");
        return jsonModel;
    }
}

5.启动类添加注解@EnableCircuitBreaker

@SpringBootApplication
@MapperScan("com.yc.mapper")
@EnableEurekaClient //服务启动后自动注册到eureka
@EnableCircuitBreaker//启用断路器
//@SpringCloudApplication//一注解多用
public class HystrixProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(HystrixProviderApplication.class, args);
    }
}

Hello舱壁模式—提供端

1.理论知识

  • 服务雪崩问题描述
在基于微服务的应用程序中,通常需要调用多个微服务完成一个特定任务。
这些调用默认使用相同线程,该线程是Java容器为处理所有请求预留的
在高服务器请求情况下,一个性能较低的服务会霸占java容器中绝大多数线程,而其它性能正常的服务的请求则需要等待线程资源的释放,导致整个java容器会崩溃
  • 问题原理图
    在这里插入图片描述
  • 原理图解析
Hystrix将远程服务请求托管在线程池中
即默认情况下,所有Hystrix命令(@HystrixCommand)共享同一线程池来处理请求
该线程池中持有10个线程来处理各种远程服务请求,可以是REST服务调用、数据库访问等
  • hystrix舱壁模式解决问题
舱壁模式将远程调用隔离在各个远程调用自己的线程池中,因此单个性能出问题的服务能得到控制,java容器也不会崩溃
  • hystrix舱壁模式解决原理图
    在这里插入图片描述

2.舱壁模式配置

  • 新建模块microcloud-provider-dept-hystrix-8001
  • pom.xml
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
  • 修改controller下的DeptProviderServlet
@RestController
@RequestMapping("/provider")
public class DeptProviderServlet {
    @Autowired
    private DeptService deptService;

    @RequestMapping("/findAll")
    @HystrixCommand(fallbackMethod = "getMethodCallback",//后备方法名,必须是当前类中某方法名
            //当Hystrix检测请求长时间没有响应时,执行fallbackMethod绑定的当前类同方法名的方法
            threadPoolKey = "productGetIdServiceThreadPool",//线程池标识,Hystrix会新建线程池,按照默认配置初始化该线程池
            threadPoolProperties = {//接收@HystrixProperty数组,用于配置新建的线程池
                    @HystrixProperty(name = "coreSize", value = "10"),
                    @HystrixProperty(name = "maxQueueSize", value = "10")
                    //应对线程池繁忙情况,当超过该容量,其他请求会迅速失败返回,直到又有空闲位置
                    //maxQueueSize=-1时Hystrix使用SynchronousQueue实现该队列(同步队列),意味着线程池繁忙时不再接收其它请求,直接迅速失败返回,粗略理解为该队列不存在
                    //maxQueueSize>1时Hystrix创建LinkedBlockingQueue
                    //Hystrix允许使用SizeRejectionThreshold动态变更队列容量,但该属性只有在maxQueueSize的value>0时才生效
                    //maxQueueSize属性的值只能在线程池初始化时设置
                    //netflix对线程池大小的建议: 每秒处理请求的峰值 × 99%平均响应时间 + 缓冲线程数
            }
    )
    public JsonModel fingAll(JsonModel jsonModel) {
        List<Dept> list = this.deptService.fingAll();
        jsonModel.setCode(1);
        jsonModel.setData(list);
        return jsonModel;
    }
}
  • 启动类添加注解@EnableCircuitBreaker
@SpringBootApplication
@MapperScan("com.yc.mapper")
@EnableEurekaClient //服务启动后自动注册到eureka
@EnableCircuitBreaker//启用断路器
//@SpringCloudApplication//一注解多用
public class HystrixProviderApplication {
    public static void main(String[] args) {
        SpringApplication.run(HystrixProviderApplication.class, args);
    }
}

HelloDashboard

1.理论知识

  • Dashboard 记录 HystrixCommand和HystrixObservableCommand实例在执行过程中的重要信息,对系统运维十分重要
  • 信息以 "滚动时间窗"与"桶"结合 的方式进行汇总,并在内存中驻留一段时间,以供内部或外部使用
  • 在分布式系统中有很多实例要运维和监控,这样就要开启多个窗口来监控,所以可以利用turbine和dashboard结合来对集群监控
  • Hystrix Dashboard
    在这里插入图片描述

2.Dashboard配置

  • 新建Dashboard单独服务模块microcloud-hystrix-dashboard-9001
  • 目录结构
    在这里插入图片描述
  • pom.xml
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-hystrix-dashboard</artifactId>
</dependency>
  • application.yml
server:
  port: 9001  #http://localhost:9001/hystrix
hystrix:
  dashboard:
    proxy-stream-allow-list: localhost
  • 启动类
@SpringBootApplication
@EnableHystrixDashboard
public class DashBoardApp {
    public static void main(String[] args) {
        SpringApplication.run(DashBoardApp.class,args);
    }
}
  • 在microcloud-provider-dept-hystrix-8001添加actuator配置,不会去Eureka中看

HelloTurbine

1.理论

  • 集群监控端点http://turbine-hostname:port/turbine.stream
  • Trubine汇集监控信息并将聚合后的信息提供给Dashboard
  • 原理图
    在这里插入图片描述

2.Turbine配置

  • 新建Turbine单独服务模块microcloud-turbine-7777
  • pom.xml
<dependency>
	<groupId>org.springframework.cloud</groupId>
	<artifactId>spring-cloud-starter-netflix-turbine</artifactId>
</dependency>
  • application.yml
server:
  port: 7777

eureka: #turbine需要通过eureka获取服务列表,所以需要配置eureka
  client:
    register-with-eureka: false
    service-url:
      defaultZone: http://eureka1:7001/eureka/,http://eureka2:7002/eureka/,http://eureka3:7003/eureka/

turbine:
  app-config: MICROCLOUD-PROVIDER-DEPT #需要收集信息的服务名(eureka中的服务)
  cluster-name-expression: new String("default")
  combine-host-port: true #同主机上的服务通过主机名和端口号的组合来进行区分,默认以host来区分
  • 启动类
@SpringBootApplication
@EnableTurbine
public class TurbineApp {
    public static void main(String[] args) {
        SpringApplication.run(TurbineApp.class,args);
    }
}
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值