SpringCloud H版系列7--Hystrix断路器

本文详细介绍了SpringCloud中Hystrix组件的使用,包括其设计目标、实现机制,以及服务降级和熔断的概念。通过创建微服务实例展示了如何在服务端和消费端实现Hystrix,提供了具体的代码示例,如设置超时、熔断器和回退逻辑。此外,还包含了服务端和消费端的测试步骤。
摘要由CSDN通过智能技术生成


书接上文,继续跟着周阳老师学习SpringCloud的Hystrix,特此整理如下

一、Hystrix

在分布式环境中,许多服务依赖项中的一些必然会失败。Hystrix是一个库,通过添加延迟容忍和容错逻辑,帮助你控制这些分布式服务之间的交互。Hystrix通过隔离服务之间的访问点、停止级联失败和提供回退选项来实现这一点,所有这些都可以提高系统的整体弹性。

1.1 Hystrix被设计的目标

(1)对通过第三方客户端库访问的依赖项(通常是通过网络)的延迟和故障进行保护和控制。
(2)在复杂的分布式系统中阻止级联故障。
(3)快速失败,快速恢复。
(4)回退,尽可能优雅地降级。
(5)启用近实时监控、警报和操作控制。

1.2 Hystrix是如何实现它的目标的

(1)用一个HystrixCommand 或者 HystrixObservableCommand
(这是命令模式的一个例子)包装所有的对外部系统(或者依赖)的调用,典型地它们在一个单独的线程中执行。
(2)调用超时时间比你自己定义的阈值要长。有一个默认值,对于大多数的依赖项你是可以自定义超时时间的。
(3)为每个依赖项维护一个小的线程池(或信号量);如果线程池满了,那么该依赖性将会立即拒绝请求,而不是排队。
(4)调用的结果有这么几种:成功、失败(客户端抛出异常)、超时、拒绝。
(5)在一段时间内,如果服务的错误百分比超过了一个阈值,就会触发一个断路器来停止对特定服务的所有请求,无论是手动的还是自动的。
(6)当请求失败、被拒绝、超时或短路时,执行回退逻辑。 近实时监控指标和配置变化。

二、服务降级与服务熔断

2.1服务降级主要有三种情况

(1)访问超时
(2)运行错误
(3)宕机

2.2服务熔断

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

在SpringCloud中,熔断机制是通过Hystrix实现,Hystrix会监控微服务间调用的状况。当失败的调用达到阈值(默认是5秒内20次调用失败),则会启动熔断机制,熔断机制注解为@HystrixCommand。

三、创建微服务,服务端cloud-provider-hystrix-payment8001

application.yml

server:
  port: 8001

eureka:
  client:
    register-with-eureka: true   #是否将自己注册到注册中心,集群必须设置为true配合ribbon
    fetch-registry: true    #是否从服务端抓取已有的注册信息
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka # ,http://eureka7002.com:7002/eureka

spring:
  datasource:
    type: com.alibaba.druid.pool.DruidDataSource
    driver-class-name: org.gjt.mm.mysql.Driver
    url: jdbc:mysql://127.0.0.1:3306/test?useUnicode=true&characterEncoding=utf-8&useSSL=false
    username: root
    password: 1234
  application:
    name: cloud-provider-hystrix-payment

PaymentHystrixMain8001

@SpringBootApplication
@EnableEurekaClient
@EnableCircuitBreaker  //激活服务降级注解
public class PaymentHystrixMain8001 {
    public static void main(String[] args) {
        SpringApplication.run(PaymentHystrixMain8001.class,args);
    }

    /**
     * 此配置是为了服务监控而配置,与服务器容错本身无关,springcloud升级后的坑
     * ServletRegistrationBean因为springboot的默认路径不是/hystrix.stream
     * 只要在自己的项目里配置上下文的servlet就可以了
     */
    @Bean
    public ServletRegistrationBean getservlet(){
        HystrixMetricsStreamServlet streamServlet = new HystrixMetricsStreamServlet();
        ServletRegistrationBean<HystrixMetricsStreamServlet> registrationBean = new ServletRegistrationBean<>(streamServlet);
        registrationBean.setLoadOnStartup(1);
        registrationBean.addUrlMappings("/hystrix.stream");
        registrationBean.setName("HystrixMetricsStreamServlet");
        return registrationBean;
    }
}

PaymentController

@RestController
@Slf4j
public class PaymentController {
    @Autowired
    private PaymentService paymentService;
    @Value("${server.port}")
    private String serverPort;

    //正常访问,肯定ok的方法
    @GetMapping("/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id){
      String result = paymentService.papymentInfo_OK(id);
      log.info("***********result:"+result);
      return result;
    }
    
    //超时方法
    @GetMapping("/payment/hystrix/timeout/{id}")
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
      String result = paymentService.paymentInfo_TimeOut(id);
      log.info("***********result:"+result);
      return result;
    }

    // 服务熔断
    @GetMapping("/payment/circuit/{id}")
    public String paymentCircuitBreaker(@PathVariable("id") Integer id) {
        String result = paymentService.paymentCircuitBreaker(id);
        log.info("****result: " + result);
        return result;
    }
}

PaymentService

@Service
public class PaymentService {
    //正常访问,肯定ok的方法
    public String papymentInfo_OK(Integer id){
        return "线程池:"+Thread.currentThread().getName()+" paymentInfo_OK,id:"+id+"\t";
    }

    //超时方法
    @HystrixCommand(fallbackMethod = "paymentInfo_TimeOutHandler",commandProperties = {
            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "5000")
    })
    public String paymentInfo_TimeOut(Integer id){
        int timeNumber = 3000;
        // int timeNumber = 10/0;
        try {
            TimeUnit.SECONDS.sleep(timeNumber);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "线程池: " + Thread.currentThread().getName() + " PaymenyInfo_TimeOut,id: " + id + "\t" + "O(∩_∩)O哈哈~" + " 耗时" + timeNumber + "毫秒";
    }

    public String paymentInfo_TimeOutHandler(Integer id) {
        return "线程池: " + Thread.currentThread().getName() + " 8001系统繁忙系统报错,请稍后再试id: " + id + "\t" + "( Ĭ ^ Ĭ )";
    }

    //CircuitBreaker断路器,测试步骤
    /*首先访问http://localhost:8001/payment/circuit/1正常返回结果
    *然后访问http://localhost:8001/payment/circuit/-1,一直重复刷新访问这个错误结果
    *当错误率达到60%.之后再访问http://localhost:8001/payment/circuit/1结果还是错误结果,因为已经熔断了
    * 但是,过10000之后会慢慢恢复,重新访问http://localhost:8001/payment/circuit/1结果又恢复正确了
    * */
    //服务熔断
    @HystrixCommand(fallbackMethod = "paymentCircuitBreaker_fallback",
            commandProperties ={
              @HystrixProperty(name="circuitBreaker.enabled",value="true"),//是否开启断路器
              @HystrixProperty(name="circuitBreaker.requestVolumeThreshold",value="10"),//请求次数
              @HystrixProperty(name="circuitBreaker.sleepWindowInMilliseconds",value="10000"),//时间窗口期
              @HystrixProperty(name = "circuitBreaker.errorThresholdPercentage",value = "60")//失败率达到多少后跳闸
    })
    public String paymentCircuitBreaker(@PathVariable("id") Integer id){
        if(id < 0){
            throw new RuntimeException("******id 不能为负数");
        }
        //hutool工具包,在cloud-api-commons的pom中已经引入
        String serialNumber = IdUtil.simpleUUID();
        return Thread.currentThread().getName()+"\t"+"调用成功,流水号:"+serialNumber;
    }

    public String paymentCircuitBreaker_fallback(@PathVariable("id") Integer id){
        return "id不能为负数,请稍后再试,┭┮﹏┭┮ ,id:"+id;
    }
}

四、服务端cloud-provider-hystrix-payment8001测试

启动cloud-eureka-server7001、cloud-provider-hystrix-payment8001

访问http://eureka7001.com:7001/
在这里插入图片描述
执行http://localhost:8001/payment/hystrix/ok/31
在这里插入图片描述
执行http://localhost:8001/payment/hystrix/timeout/3,等待3秒钟后,才有反馈结果
在这里插入图片描述

五、创建微服务,消费端cloud-consumer-feign-hystrix-order80

application.yml

server:
  port: 80

eureka:
  client:
    register-with-eureka: false   #是否将自己注册到注册中心,集群必须设置为true配合ribbon
    service-url:
      defaultZone: http://eureka7001.com:7001/eureka
      # ,http://eureka7002.com:7002/eureka
##设置feign客户端超时时间
#ribbon:
#  ReadTimeout: 5000
#  ConnectTimeout: 5000

#用于服务降级,在注解FeignClient中添加FallBack属性值
feign:
  hystrix:
    enabled: true

OrderhystrixMain80

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

OrderHystrixController

@RestController
@Slf4j
@DefaultProperties(defaultFallback = "payment_Global_FallbackMethod")
public class OrderHystrixController {

    @Resource
    private PaymentHystrixService paymentHystrixService;

    @GetMapping("/consumer/payment/hystrix/ok/{id}")
    public String paymentInfo_OK(@PathVariable("id") Integer id){
        String result = paymentHystrixService.paymentInfo_OK(id);
        return result;
    }

//    @GetMapping("/consumer/payment/hystrix/timeout/{id}")
//    public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
//        String result = paymentHystrixService.paymentInfo_TimeOut(id);
//        return result;
//    }

    @GetMapping("/consumer/payment/hystrix/timeout/{id}")
//    @HystrixCommand(fallbackMethod = "PaymentTimeOutFallbackMethod",commandProperties = {
//            @HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds",value = "3000")
//    })
//    如果HystrixCommand标注的类中执行超时3秒,则执行fallbackMethod的方法PaymentTimeOutFallbackMethod,兜底

    //设置服务降级注解,如果不指名具体fallbackMethod,则执行defaultFallback
    @HystrixCommand
    public String paymentInfo_TimeOut(@PathVariable("id") Integer id){
        /*故意设置5秒超时
        int timeUmber = 5;
        try {
            TimeUnit.SECONDS.sleep(timeUmber);
        } catch (Exception e) {
            e.printStackTrace();
        }
        */
        int age = 10/0;
        String result = paymentHystrixService.paymentInfo_TimeOut(id);
        return result;
    }

    public String PaymentTimeOutFallbackMethod(@PathVariable("id") Integer id) {
        return "我是消费者80,对方支付系统繁忙请10秒钟后再试或者自己运行出错请检查自己,o(╥﹏╥)o";
    }

    //下面是全局fallback方法
    public String payment_Global_FallbackMethod(){
        return "Global异常处理信息,请稍后再试,o(╥﹏╥)o";
    }
}

PaymentHystrixService

@Component
@FeignClient(value = "CLOUD-PROVIDER-HYSTRIX-PAYMENT",fallback = PaymentFallbackService.class)
//解耦
public interface PaymentHystrixService {

    @GetMapping("/payment/hystrix/ok/{id}")
    String paymentInfo_OK(@PathVariable("id") Integer id);

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

}

PaymentFallbackService,统一为接口里面的方法进行异常处理

@Component  //该方法统一为接口里面的方法进行异常处理
public class PaymentFallbackService implements  PaymentHystrixService{
    @Override
    public String paymentInfo_OK(Integer id) {
        return "-------PaymentFallbackService fall back-paymentInfo_OK,o(╥﹏╥)o";
    }

    @Override
    public String paymentInfo_TimeOut(Integer id) {
        return "-------PaymentFallbackService fall back-paymentInfo_TimeOut,o(╥﹏╥)o";
    }
}

PaymentFallbackService

@Component  //该方法统一为接口里面的方法进行异常处理
public class PaymentFallbackService implements  PaymentHystrixService{
    @Override
    public String paymentInfo_OK(Integer id) {
        return "-------PaymentFallbackService fall back-paymentInfo_OK,o(╥﹏╥)o";
    }

    @Override
    public String paymentInfo_TimeOut(Integer id) {
        return "-------PaymentFallbackService fall back-paymentInfo_TimeOut,o(╥﹏╥)o";
    }
}

六、消费端cloud-consumer-feign-hystrix-order80测试

访问http://localhost:80/consumer/payment/hystrix/ok/1
在这里插入图片描述
访问http://localhost:80/consumer/payment/hystrix/timeout/1

如果HystrixCommand标注的类中执行超时3秒,则执行fallbackMethod的方法PaymentTimeOutFallbackMethod,兜底。

设置服务降级注解,如果不指名具体fallbackMethod,则执行defaultFallback,配置全局统一Fallback异常。
在这里插入图片描述
设置服务降级注解,指名具体fallbackMethod为PaymentTimeOutFallbackMethod
,则执行http://localhost:80/consumer/payment/hystrix/timeout/1
在这里插入图片描述

源码下载地址

spring-cloud-01

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值