【从0到1设计一个网关】基于Hystrix实现熔断降级

上文我们已经成功实现了请求重试与请求限流,接下来我们开始实现熔断与服务降级。 熔断与服务降级,在SpringCloud中设计到的就是我们的hystrix,这里我们也将会考虑配合hystrix来实现熔断与服务降级。 如果不了解hystix的可以先进行一下了解。

依赖引入

由于这里我是用的是基于hystrix的熔断降级,所以首先需要将服务整合hystrix

c 复制代码
	<hystrix.core.version>1.5.12</hystrix.core.version>
        <hystrix.javanica.version>1.5.12</hystrix.javanica.version>
        <hystrix.metrics.version>1.5.12</hystrix.metrics.version>
               <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-core</artifactId>
            <version>${hystrix.core.version}</version>
        </dependency>
        <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-metrics-event-stream</artifactId>
            <version>${hystrix.metrics.version}</version>
        </dependency>
        <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-javanica</artifactId>
            <version>${hystrix.javanica.version}</version>
        </dependency>

引入如上的依赖之后,我们就可以开始基于hystrix编写如何进行熔断限流了。 我先贴出一套代码来大致介绍一下如何使用hystrix实现熔断降级。

java 复制代码
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixThreadPoolProperties;

public class MyHystrixCommand extends HystrixCommand<String> {

    private final String fallbackValue;

    protected MyHystrixCommand(String fallbackValue) {
        super(Setter
            .withGroupKey(HystrixCommandGroupKey.Factory.asKey("MyGroup"))
            .andCommandKey(HystrixCommandKey.Factory.asKey("MyCommand"))
            .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                .withExecutionTimeoutInMilliseconds(1000)) // 设置超时时间
            .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
                .withCoreSize(10) // 设置线程池大小
            );
        this.fallbackValue = fallbackValue;
    }

    @Override
    protected String run() throws Exception {
        // 执行你的业务逻辑
        return "Result of the actual operation";
    }

    @Override
    protected String getFallback() {
        // 执行降级逻辑
        return fallbackValue;
    }
}

上述代码中,我创建了一个自定义的 MyHystrixCommand 类,继承自 HystrixCommand 类。在该类的构造函数中,你可以配置Hystrix的一些属性,如组、命令名称、执行超时等。然后,你需要实现 run 方法来执行实际的业务逻辑,以及 getFallback 方法来执行降级逻辑。

接下来,你可以在应用中使用这个自定义的Hystrix命令:

java 复制代码
String result = new MyHystrixCommand("Fallback Value").execute();

通过调用 execute 方法,你可以执行Hystrix命令,如果发生熔断,将会执行降级逻辑,返回降级值。

这种方式允许你更细粒度地控制熔断和降级的行为,但需要手动配置Hystrix的属性,如超时时间、线程池大小等。你可以根据具体需求进行定制。 所以,根据上面的情况,我们就已经大概知道了如何基于hystrix实现一套熔断降级的逻辑了。

服务降级

那么接下来我们来编写具体的实现代码。 首先,我们需要在配置中心的配置中添加出来对hystrix的配置。

java 复制代码
"hystrixConfigs":[{
                "path":"/http-server/ping",
                "timeoutInMilliseconds":5000,
                "threadCoreSize":2,
                "fallbackResponse":"熔断超时"
            }]

之后,我们知道我们的具体执行逻辑是走过滤器的,所以我们需要在我们的路由过滤器这里添加额外的对hystrix的配置,来监测我们最后转发请求的时候,如果这个请求处理失败或者超时时,要让他进行熔断降级的逻辑。

java 复制代码
 @Override
    public void doFilter(GatewayContext gatewayContext) throws Exception {
        //首先获取熔断降级的配置
        Optional<Rule.HystrixConfig> hystrixConfig = getHystrixConfig(gatewayContext);
        //如果存在对应配置就走熔断降级的逻辑
        if (hystrixConfig.isPresent()) {
            routeWithHystrix(gatewayContext, hystrixConfig);
        } else {
            route(gatewayContext, hystrixConfig);
        }
    }
 /**
     * 获取hystrix的配置
     *
     * @param gatewayContext
     * @return
     */
    private static Optional<Rule.HystrixConfig> getHystrixConfig(GatewayContext gatewayContext) {
        Rule rule = gatewayContext.getRule();
        Optional<Rule.HystrixConfig> hystrixConfig =
                rule.getHystrixConfigs().stream().filter(c -> StringUtils.equals(c.getPath(),
                        gatewayContext.getRequest().getPath())).findFirst();
        return hystrixConfig;
    }

可以看到,我上面的代码就是从配置中心中获取到hystrix的配置,然后判断如果存在熔断降级的配置就走熔断降级的逻辑。 原先的没有熔断降级时候的route逻辑不用改变,我们需要额外创建一个方法,当存在熔断降级逻辑时走这个方法。 这里就按照我们上一节提到的代码的编写方式,进行代码的编写和配置即可。

java 复制代码
 /**
     * 根据提供的GatewayContext和Hystrix配置,执行路由操作,并在熔断时执行降级逻辑。
     * 熔断会发生在:
     * 当 Hystrix 命令的执行时间超过配置的超时时间。
     * 当 Hystrix 命令的执行出现异常或错误。
     * 当连续请求失败率达到配置的阈值。
     * @param gatewayContext
     * @param hystrixConfig
     */
    private void routeWithHystrix(GatewayContext gatewayContext, Optional<Rule.HystrixConfig> hystrixConfig) {

        HystrixCommand.Setter setter =  //进行分组
                HystrixCommand.Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey(gatewayContext.getUniqueId()))
                        .andCommandKey(HystrixCommandKey.Factory.asKey(gatewayContext.getRequest().getPath()))
                        //线程池大小设置
                        .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter()
                                .withCoreSize(hystrixConfig.get().getThreadCoreSize()))
                        .andCommandPropertiesDefaults(HystrixCommandProperties.Setter()
                                //线程池
                                .withExecutionIsolationStrategy(HystrixCommandProperties.ExecutionIsolationStrategy.THREAD)
                                //超时时间
                                .withExecutionTimeoutInMilliseconds(hystrixConfig.get().getTimeoutInMilliseconds())
                                .withExecutionIsolationThreadInterruptOnTimeout(true)
                                .withExecutionTimeoutEnabled(true));

        // 创建一个新的HystrixCommand对象,用于执行实际的路由操作。
        new HystrixCommand<Object>(setter) {
            @Override
            protected Object run() throws Exception {
                // 在Hystrix命令中执行路由操作,这是实际的业务逻辑。
                route(gatewayContext, hystrixConfig).get();
                return null;
            }

            @Override
            protected Object getFallback() {
                // 当熔断发生时,执行降级逻辑。
                // 设置网关上下文的响应信息,通常包括一个降级响应。
                gatewayContext.setResponse(hystrixConfig.get().getFallbackResponse());
                gatewayContext.written();
                return null;
            }
        }.execute(); // 执行Hystrix命令。
    }

效果演示

上面的代码编写完毕之后,我们就已经完成了熔断降级了。 接下来我们来看看具体的效果。 启动后端服务,并且让后端服务进行长时间的阻塞。 那么此时就会触发一个超时的异常,此时就会出现熔断降级,

相关推荐
潘多编程20 分钟前
Spring Boot微服务架构设计与实战
spring boot·后端·微服务
2402_8575893625 分钟前
新闻推荐系统:Spring Boot框架详解
java·spring boot·后端
2401_8576226627 分钟前
新闻推荐系统:Spring Boot的可扩展性
java·spring boot·后端
Amagi.2 小时前
Spring中Bean的作用域
java·后端·spring
2402_857589362 小时前
Spring Boot新闻推荐系统设计与实现
java·spring boot·后端
J老熊2 小时前
Spring Cloud Netflix Eureka 注册中心讲解和案例示范
java·后端·spring·spring cloud·面试·eureka·系统架构
Benaso2 小时前
Rust 快速入门(一)
开发语言·后端·rust
sco52822 小时前
SpringBoot 集成 Ehcache 实现本地缓存
java·spring boot·后端
原机小子3 小时前
在线教育的未来:SpringBoot技术实现
java·spring boot·后端
吾日三省吾码3 小时前
详解JVM类加载机制
后端