05、SpringCloud之Hystrix组件学习笔记(一)

简介: 05、SpringCloud之Hystrix组件学习笔记(一)

一、服务雪崩


1.1、引出服务雪崩


分布式场景下:



在高并发场景下:由于服务之间会进行调用,一旦某个服务不可用,那么就会出现服务雪崩


一旦服务链路中出现了某个服务不可用,那么就会影响整个链路,从而出现不可预计的问题!



服务雪崩的本质:由于调用的服务方不可用,就会导致对应的线程没有及时回收。


解决关键:不管是调用成功还是失败,只要线程可以及时回收,就可以解决服务雪崩。


1.2、雪崩三阶段


1、服务不可用:硬件故障/程序Bug/缓存击穿/用户大量请求。


2、调用端重试加大流量:用户重试/代码逻辑重试。


3、服务调用者不可用:同步等待造成的资源耗尽。


1.3、如何解决服务雪崩


方案描述:


1、应用扩容:加机器或升级硬件。


2、流控:限流/关闭重试。


3、缓存预加载。


4、服务降级:服务接口拒绝服务/页面拒绝服务/延迟持久化/随机拒绝服务。


5、服务熔断。


方案一:修改调用的超时时长(不推荐)

思路:将服务间的调用超时时长改小,这样就可以让线程及时回收,保证服务可用


优点:非常简单,也可以有效的解决服务雪崩


缺点:不够灵活,有的服务需要更长的时间去处理(写库,整理数据)


方案二:设置拦截器(设置断路器)

思路:在调用远程服务前来设置一个拦截器来进行服务状态判断。



二、认识Hystrix


2.1、服务熔断概念及断路器


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


解决方案:断路器模式。


断路器原理:当远程服务被调用时,断路器将监视这个调用,如调用时间太长,断路器将会介入并中断调用。 断路器将监视所有远程资源的调用,如对某个远程资源的调用失败次数足够多,那么断路器会出现并采取快速失败,阻止将来调用失败的远程资源


状态图:



解析:


断路器最开始处于closed状态,一旦检测到的错误到达一定数量,断路器便转为open状态(断路器打开);
此时到达reset timeout时间会转移到half open状态;
尝试放行一部分请求到后端,一旦检测成功便回归到closed状态,即恢复服务


断路器实现方案:阿里的Sentinel、netflix的Hystric。


2.2、Spring Cloud Hystrix介绍


熔断器,也叫断路器!(正常情况下 断路器是关的 只有出了问题才打开)用来保护微服务不雪崩的方法。思想和我们上面画的拦截器一样。


Hystrix 是 Netflix 公司开源的一个项目,它提供了熔断器功能,能够阻止分布式系统中出现联动故障。Hystrix 是通过隔离服务的访问点阻止联动故障的,并提供了故障的解决方案,从 而提高了整个分布式系统的弹性。


例如:微博 弹性云扩容 Docker K8s。


三、快速入门Hystrix


3.1、搭建基础服务(服务提供方以及消费方)


项目版本:SpringBoot:2.3.12.RELEASE、SpringCloud:Hoxton.SR12


<parent>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-parent</artifactId>
    <version>2.3.12.RELEASE</version>
    <relativePath/> <!-- lookup parent from repository -->
</parent>
<properties>
    <java.version>1.8</java.version>
    <spring-cloud.version>Hoxton.SR12</spring-cloud.version>
</properties>



注册中心使用之前案例中的Eureka,然后在04-hystrix中创建两个服务来进行demo展示。


1、创建借车服务:01-rent-car-service


<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
    <groupId>org.springframework.cloud</groupId>
    <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId>
</dependency>
<dependency>
    <groupId>org.projectlombok</groupId>
    <artifactId>lombok</artifactId>
    <optional>true</optional>
</dependency>



①配置文件application.yml


server:
  port: 8081
spring:
  application:
    name: rent-car-service
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    hostname: localhost
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}


②在启动器中添加开启EurekaClient:


@EnableEurekaClient


③添加控制器:controller/RentController.java


package com.changlu.rentcarservice.controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * @Description:
 * @Author: changlu
 * @Date: 9:18 PM
 */
@RestController
public class RentCarController {
    @GetMapping("/rent")
    public String rent() {
        return "租车成功!";
    }
}


2、创建消费者服务:02-customer-service



①配置文件:application.yml:


server:
  port: 8082
spring:
  application:
    name: customer-service
eureka:
  client:
    service-url:
      defaultZone: http://localhost:8761/eureka
  instance:
    hostname: localhost
    instance-id: ${eureka.instance.hostname}:${spring.application.name}:${server.port}


②在启动器中添加服务发现注解以及扫描feign包注解


@EnableEurekaClient
@EnableFeignClients(basePackages = "com.changlu.customerservice.feign") //开启feign包扫描


③创建feign包,添加租车服务的接口方法


package com.changlu.customerservice.feign;
import org.springframework.cloud.openfeign.FeignClient;
import org.springframework.web.bind.annotation.GetMapping;
/**
 * @Description:
 * @Author: changlu
 * @Date: 9:30 PM
 */
@FeignClient("rent-car-service")  //对应服务名
public interface CustomerRentFeign {
    @GetMapping("/rent")
    public String rent();
}




④创建控制器:controller/CustomerController.java


package com.changlu.customerservice.controller;
import com.changlu.customerservice.feign.CustomerRentFeign;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
 * @Description:
 * @Author: changlu
 * @Date: 9:28 PM
 */
@RestController
public class CustomerController {
    @Autowired
    private CustomerRentFeign customerRentFeign;//远程调用
    @GetMapping("/customerRent")
    public String customerRent() {
        System.out.println("来进行访问租车了!");
        //进行一个远程调用
        String rent = customerRentFeign.rent();
        return rent;
    }
}


至此两个服务目前已经搭建完成!


3.2、启动服务,引入服务调用失败问题


启动一个注册中心以及刚刚创建的两个服务:



访问一下(正常):http://localhost:8082/customerRent



然后我们把RentCar服务关闭掉之后,再次访问:



若是服务不可用,那么就会出现服务调用失败的情况,对于在高并发情况下若是频繁出现这种情况则会导致服务雪崩,从而出现大问题!


那么如何解决呢?


3.3、解决方案:使用Hystrix熔断器


引入过程:


①引入Hystrix依赖:其实不引入也是可以的,因为feign依赖中就自带hystrix依赖


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


②在配置中开启Hystrix熔断器:在Hoxton.SR12版本中默认是关闭的


feign:
  hystrix:
    enabled: true  # 熔断器开启


③编写对应feign的熔断器



package com.changlu.customerservice.feign.hystrix;
import com.changlu.customerservice.feign.CustomerRentFeign;
import org.springframework.stereotype.Component;
/**
 * @Description: 消费者-借车熔断器
 * @Author: changlu
 * @Date: 9:19 AM
 */
@Component
public class CustomerRentHystrix implements CustomerRentFeign {
    @Override
    public String rent() {
        return "租车成功!(熔断器)";
    }
}



④在对应的feign中添加相应的fallback属性来指定对应的熔断方法



@FeignClient(value = "rent-car-service", fallback = CustomerRentHystrix.class)


此时我们再来测试一下!



相关文章
|
13小时前
|
SpringCloudAlibaba Java 网络架构
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(二)Rest微服务工程搭建
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(二)Rest微服务工程搭建
63 0
|
13小时前
|
SpringCloudAlibaba Java 网络架构
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(七)Spring Cloud Gateway服务网关
123 0
|
13小时前
|
监控 Java 微服务
第八章 Spring Cloud 之 Hystrix
第八章 Spring Cloud 之 Hystrix
14 0
|
13小时前
Springcloud-ribbon和hystrix配置
Springcloud-ribbon和hystrix配置
10 0
|
13小时前
|
SpringCloudAlibaba 负载均衡 Java
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(目录大纲)
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(目录大纲)
72 1
|
13小时前
|
Java Nacos Sentinel
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(九)Nacos+Sentinel+Seata
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(九)Nacos+Sentinel+Seata
240 0
|
13小时前
|
消息中间件 SpringCloudAlibaba Java
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(八)Config服务配置+bus消息总线+stream消息驱动+Sleuth链路追踪
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(八)Config服务配置+bus消息总线+stream消息驱动+Sleuth链路追踪
793 0
|
13小时前
|
SpringCloudAlibaba Java 测试技术
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(六)Hystrix(豪猪哥)的使用
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(六)Hystrix(豪猪哥)的使用
47 1
|
13小时前
|
SpringCloudAlibaba 负载均衡 Java
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(五)OpenFeign的使用
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(五)OpenFeign的使用
47 0
|
13小时前
|
负载均衡 算法 Java
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(四)Ribbon的使用
【Springcloud Alibaba微服务分布式架构 | Spring Cloud】之学习笔记(四)Ribbon的使用
29 0