使用Hystrix断路器(一)处理失败和延迟,管理断路器阈值

目录

一、什么是Hystrix断路器模式

二、本文用到的工程名列表

三、声明使用断路器

1. 在eurekaconsumer项目中添加依赖

2. 在eurekaconsumer项目启动类中启用Hystrix

3. 在eurekaconsumer项目中为方法定义一个断路器切面

4. 测试断路器的运行效果

5. 使用断路器缓解延迟

6. 管理断路器的阈值


一、什么是Hystrix断路器模式

在微服务中断路器在方法执行失败时可以优雅的处理失败,避免跨调用堆栈产生级联失败。

断路器起初会处于关闭状态,允许进行方法的调用。如果因为某种原因,方法调用失败了,断路器就会打开,就不会对失败的方法再执行调用了。此时会调用一个后备方法代替失败的方法返回结果。在调用后备方法的过程中断路器偶尔会进入半开状态,去再次尝试调用发生失败的方法:如果依然失败,断路器就恢复打开状态;如果调用成功,它会认为问题已经解决,断路器回到闭合状态。

二、本文用到的工程名列表

Eureka快速入门篇(一)中的两个项目:

eurekaserver(注册中心,server.port=8761)

eurekauser(微服务提供者,server.port=8081)

Eureka快速入门篇(二)中的项目:

eurekaconsumer(微服务消费者,server.port=8083)

三、声明使用断路器

1. 在eurekaconsumer项目中添加依赖

2. 在eurekaconsumer项目启动类中启用Hystrix

添加@EnableHystrix注解,启动Hystrix断路器。代码如下:

package com.eurekaconsumer;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
import org.springframework.cloud.netflix.hystrix.EnableHystrix;
import org.springframework.context.annotation.Bean;
import org.springframework.web.client.RestTemplate;

/**
 * @EnableEurekaClient只适用于Eureka作为注册中心,@EnableDiscoveryClient 可以是其他注册中心。
 */
@SpringBootApplication
@EnableEurekaClient //启动Eureka客户端
@EnableHystrix //添加@EnableHystrix注解,启动Hystrix断路器
public class EurekaconsumerApplication {

    public static void main(String[] args) {
        SpringApplication.run(EurekaconsumerApplication.class, args);
    }


    /**
     * 创建一个 RestTemplate 实例
     * 并开启客户端负载均衡,@LoadBalanced这个注解是让 RestTemplate 开启负载均衡的能力
     * 2022年5月11日14:59:09
     * @return
     */
    @Bean
    @LoadBalanced
    public RestTemplate restTemplate() {
        return new RestTemplate();
    }

}

3. 在eurekaconsumer项目中为方法定义一个断路器切面

任何使用@HystrixCommand注解的方法都会为其声明一个断路器切面。

使用注解:@HystrixCommand(fallbackMethod = "getDefaultJson"),并提供后备方法getDefaultJson()。代码如下:

package com.eurekaconsumer;

import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

/**
 * 服务消费者类,消费Eureka中注册的服务
 * 2022年5月11日
 */
@RestController
public class RestConsumeEureka {

    @Value("${server.port}")
    private String port;

    private RestTemplate rest;

    /**
     * 构造方法注入EurekaconsumerApplication启动类中定义的@Bean(RestTemplate)
     * @param rest
     */
    public RestConsumeEureka(@LoadBalanced RestTemplate rest) {
        this.rest = rest;
    }

    /**
     * @HystrixCommand,为方法提供断路器,断路器为getjsonStr方法提供失败防护,一段此方法失败则访问默认的后备方法getDefaultJson
     * 如果getjsonStr方法抛出了未捕获的异常,那么断路器将会捕获异常并将方法调用重定向到后备方法(getDefaultJson)上。
     * @HystrixCommand注解为方法声明一个断路器切面,并指明fallbackMethod(后备方法)
     * @return
     */
    @GetMapping(path = "/getmyjsonStr")
    @HystrixCommand(fallbackMethod = "getDefaultJson") //@HystrixCommand注解为方法声明一个断路器切面,并指明fallbackMethod(后备方法)
    public String getjsonStr(){
        System.out.println("消费Eureka中注册的服务。。。");
        String ret=rest.getForObject("http://EUREKAUSER/jsondata/getjData",String.class);
        System.out.println(ret);
        return ret;
    }

    /**
     * 断路器后备方法,getjsonStr()方法执行失败时调用
     * 返回一个和getjsonStr()方法返回值格式相同的默认json数据
     * @return
     */
    public String getDefaultJson(){
        System.out.println("getDefaultJson断路器后备方法执行。。。");
        String jsonStr = "后备方法getDefaultJson()提供的响应......";
        String ret=jsonStr;
        System.out.println(ret);
        return ret;
    }

}

4. 测试断路器的运行效果

依次运行项目eurekaserver(注册中心,server.port=8761),eurekauser(微服务提供者,server.port=8081),eurekaconsumer(微服务消费者,server.port=8083)

此时在浏览器中访问eurekaconsumer项目的getjsonStr()方法,可以正常调用Rest服务得到json返回结果。如图:

现在关闭服务提供者项目eurekauser。再次在浏览器访问eurekaconsumer项目的getjsonStr()方法,此时将无法调用到Rest服务得到正确的json返回结果。而是返回后备方法getDefaultJson()的响应结果。如图:

5. 使用断路器缓解延迟

默认情况下,所有使用@HystrixCommand注解的方法都会在 1 秒 之后超时,并调用他们声明的后备方法。

默认 1 秒 的断路器超时时间也可以更改,自定义超时时间使用@HystrixCommand注解的commandProperties属性来实现。commandProperties属性是一个或多个@HystrixProperty注解所组成的数组。例如设置为 500 毫秒 超时:@HystrixCommand(fallbackMethod = "getDefaultJson", commandProperties = @HystrixProperty( name = "execution.isolation.thread.timeoutInMilliseconds", value = "500"))

也可以直接移除超时功能不使用,将execution.timeout.enabled属性设置为false。@HystrixCommand(fallbackMethod = "getDefaultJson", commandProperties = @HystrixProperty( name = "execution.timeout.enabled", value = "false"))

6. 管理断路器的阈值

 默认情况下,如果断路器保护的方法调用超过 20 次,而且 50% 以上的调用在 10 秒的时间内发生失败,那么断路器就会进入打开状态。所有后续的调用都将会由后备方法处理。在 5 秒之后,断路器进入半开状态,将会再次尝试调用原始的方法。

我们可以通过设置 Hystrix 命令的属性调整失败和重试的阈值:

circuitBreaker.requestVolumeThreshold: 在给定的时间范围内,方法应该被调用的次数。
circuitBreak.errorThresholdPercentage:在给定的时间范围内,方法调用产生失败的百分比。
metrics.rollingStats.timeInMilliseconds:控制请求量和错误百分比的滚动时间周期。
circuitBreaker.sleepWindowInMilliseconds:处于打开状态的断路器要经过多长时间才会进入半开状态,进入半开状态之后,将会再次尝试失败的原始方法。

如果在metrics.ollingState.timeInMilliseconds设定的时间范围内超出了circuitBreaker.requestVolumeThreshold和circuitBreaker.errorThresholdPercentage设置的值,那么断路器将会进人打开状态。在circuitBreaker.sleepWindowInMilliseconds限定的时间范围内,它会一直处于打开状态,在此之后将进入半开状态,进入半开状态之后,将会再次尝试失败的原始方法。

例如,我们调用失败的设置:将其变更为在 20 秒的时间范围内调用超过 30 次且失败率超过 25% 。代码如下:

    @HystrixCommand(fallbackMethod = "getDefaultJson",
            commandProperties = {
                    @HystrixProperty(
                            name = "circuitBreaker.requestVolumeThreshold",
                            value = "30"),
                    @HystrixProperty(
                            name = "circuitBreaker.errorThresholdPercentage",
                            value = "25"),
                    @HystrixProperty(
                            name = "metrics.rollingStats.timeInMilliseconds",
                            value = "20000"),
                    @HystrixProperty(
                            name = "circuitBreaker.sleepWindowInMilliseconds",
                            value = "60000"),
            })
    public String getjsonStr(){
        ......
    }
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值