【Hystrix】四种fallback条件 例子

本文详细介绍了Hystrix中fallback函数的四种触发情况:任务超时、抛出异常、线程池满以及熔断器打开,并通过具体示例代码演示了每种情况。

Hystrix会在以下四种情况下触发fallback函数:

1.任务超过了"withExecutionTimeoutInMilliseconds"定义的超时时间;

2.任务抛出了非HystrixBadRequestException的异常;

3.超过了线程池线程数目;

4.熔断器打开;

下面一一举例。

1.超时

public class HelloCommand extends HystrixCommand<String> {
    protected HelloCommand() {
        super(
                Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("example"))
                        .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(1000))
        );
    }

    @Override
    protected String run() throws Exception {
        Thread.sleep(2000);
        return "hello";
    }

    @Override
    protected String getFallback() {
        return "failed";
    }
}

main:

public class App 
{
    public static void main( String[] args )
    {
        try {
            System.out.println(new HelloCommand().execute());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

2.抛异常:

public class HelloCommand extends HystrixCommand<String> {
    protected HelloCommand() {
        super(
                Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("example"))
                        .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(1000))
        );
    }

    @Override
    protected String run() throws Exception {
        throw new NullPointerException();
    }

    @Override
    protected String getFallback() {
        return "failed";
    }
}

main:

public class App 
{
    public static void main( String[] args )
    {
        try {
            System.out.println(new HelloCommand().execute());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

3.超过线程池线程数目

public class HelloCommand extends HystrixCommand<String> {
    protected HelloCommand() {
        super(
                Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("example"))
                        .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(2000))
                        .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(3))
        );
    }

    @Override
    protected String run() throws Exception {
        Thread.sleep(1000);
        return "hello";
    }

    @Override
    protected String getFallback() {
        return "failed";
    }
}

main: 

public class App 
{
    public static void main( String[] args )
    {
        try {
            for (int i = 0 ; i < 4; i++){
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(new HelloCommand().execute());
                    }
                }).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

结果会打印:

failed
hello
hello
hello

可以看到第四个任务先打印,说明在前三个执行时,第四个被直接判定为fail,第一个打印出来。原因就是线程池只配置了三个线程,所以第四个任务没有被执行,直接fail。

当然线程池的maxQueueSize参数默认是-1,表示线程池的等待队列为0,只要核心线程池没有空闲,就fail。

4.熔断器打开。

那么就得知道什么时候熔断器会打开。

如果在10s有多于circuitBreakerSleepWindowInMilliseconds个请求到达,而且有多于circuitBreakerErrorThresholdPercentage百分比的请求失败,则会导致熔断器打开,后续的circuitBreakerSleepWindowInMilliseconds时间段内的请求会直接fail。

public class HelloCommand extends HystrixCommand<String> {
    protected HelloCommand() {
        super(
                Setter.withGroupKey(HystrixCommandGroupKey.Factory.asKey("example"))
                        .andCommandPropertiesDefaults(HystrixCommandProperties.Setter().withExecutionTimeoutInMilliseconds(500)
                                .withCircuitBreakerRequestVolumeThreshold(3)
                                .withCircuitBreakerErrorThresholdPercentage(75))
                        .andThreadPoolPropertiesDefaults(HystrixThreadPoolProperties.Setter().withCoreSize(100))
        );
    }

    @Override
    protected String run() throws Exception {
        Thread.sleep(1000);
        return "hello";
    }

    @Override
    protected String getFallback() {
        return "failed";
    }
}

main:

public class App 
{
    public static void main( String[] args )
    {
        try {
            for (int i = 0 ; i < 4; i++){
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(new HelloCommand().execute());
                    }
                }).start();
                Thread.sleep(1000);
            }
            for (int i = 0 ; i < 4; i++){
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        System.out.println(new HelloCommand().execute());
                    }
                }).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

结果:

failed
failed
failed
failed
failed
failed
failed
failed

总共会有8个failed打印,因为总共8个任务。

但是前四个是间隔一定时间打印一个,后面四个是同时秒打出来。

因为配置了circuitBreakerSleepWindowInMilliseconds为3。第一个for循环里的四个任务正好保证了每10秒内有大于3个任务达到,那么会触发熔断器监控逻辑,这个四个任务执行时间是1s,而超时阈值是0.5s,那么每一个任务最重都会超时。所以第四个任务fail之后,熔断器已经打开了。这四个任务会执行到run方法,所以是执行了0.5s才打印的。

第二个for循环里的任务根本不会执行,因为执行时熔断器打开了,没有sleep直到超时,而是直接秒fail,所以同时打印。

03-13
### Hystrix 使用指南和最佳实践 Hystrix 是 Netflix 开源的一款用于处理分布式系统的延迟和容错的库,主要应用于微服务架构中的断路器模式实现。以下是有关 Hystrix 的使用方法、配置以及一些最佳实践。 #### 基本概念 Hystrix 提供了一种机制,在远程调用失败或者超时时保护并控制依赖的服务交互。它通过隔离点之间的访问来防止级联故障,并提供回退选项以增强系统的弹性[^1]。 #### 配置与使用 为了集成 Hystrix 到项目中,通常需要引入相应的 Maven 或 Gradle 依赖项。下面是一个简单的 Spring Cloud 中使用的例子: ```xml <dependency> <groupId>com.netflix.hystrix</groupId> <artifactId>hystrix-core</artifactId> <version>1.5.18</version> </dependency> ``` 接着可以通过 `@EnableCircuitBreaker` 注解启用断路器功能,并在具体的方法上标注 `@HystrixCommand` 来定义命令行为及其回退逻辑。 ```java import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand; import org.springframework.stereotype.Service; @Service public class MyService { @HystrixCommand(fallbackMethod = "fallback") public String callExternalService() { // 调用外部服务的代码 return externalCall(); } private String fallback() { return "Fallback response"; } } ``` 上述代码展示了如何设置一个带有默认回退方法的基础 Hystrix 命令。如果主业务逻辑执行过程中出现问题,则会触发指定的回退函数。 #### 性能优化与监控 除了基础的功能外,还需要关注性能调整方面的工作。比如可以自定义线程池大小、请求超时时间等参数;同时利用 Turbine 收集多个实例上的指标数据进行集中化展示以便于实时监测整个集群的状态变化情况[^4]。 另外值得注意的是随着技术栈的发展趋势,Hystrix 已经逐渐被 Resilience4j 所取代,后者更加轻量级且易于维护,特别是在响应式编程场景下表现尤为突出[^2]. #### 最佳实践总结 - **合理划分模块**: 将不同类型的请求分配到独立的资源组里运行,这样即使某个部分出了差错也不会影响其他正常工作的组件. - **设定恰当阈值**: 根据实际情况调整熔断条件(如错误百分比),既不过早也不过晚地激活防护措施. - **定期测试恢复能力**: 不仅要验证常规操作流程下的正确性还要模拟各种异常状况下来评估整体健壮程度. ---
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值