Hystrix 学习 3 : 调用失败时的fallback机制

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/andy_zhang2007/article/details/88380456

本文是本人学习Hystrix总结的第三篇,仍然是通过例子程序学习使用Hystrix,模拟一个远程调用,并调整Hystrix的执行参数和远程调用的参数观察超时发生时fallback机制生效的情形,本应用特征如下 :

  1. java 项目 ;
    • 暂不涉及结合Spring使用,以便专注于Hystrix自身;
  2. 使用junit 观察运行效果 ;
  3. 使用 maven 管理依赖;

这里所模拟的远程调用通过sleep阻塞线程一段时间模拟一个耗时的远程调用,并无真正的远程调用发生。

1. pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>tut.zero</groupId>
    <artifactId>hystrix</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>com.netflix.hystrix</groupId>
            <artifactId>hystrix-core</artifactId>
            <version>1.5.18</version>
        </dependency>
        <!-- test -->
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
    </dependencies>
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <configuration>
                    <source>1.8</source>
                    <target>1.8</target>
                    <encoding>UTF-8</encoding>
                </configuration>
            </plugin>
        </plugins>
    </build>
</project>

2. 模拟一个远程服务调用

package tut.zero.middle;

/**
 * 模拟一个远程服务调用
 */
public class MockRemoteService {

    private long wait;

    /**
     * @param wait 模拟远程调用所消耗的时间,单位 : 毫秒
     * @throws InterruptedException
     */
    public MockRemoteService(long wait)   {
        this.wait = wait;
    }

    String execute() throws InterruptedException {
        Thread.sleep(wait);
        return "SUCCESS";
    }
}

这是一个纯粹通过Java模拟远程调用的类,通过Thread.sleep()来模拟远程调用的执行耗时,而并不真正发生远程调用。该类和Hystrix还没有任何关系。

2. 定义封装远程调用的Hystrix Command,带fallback实现

package tut.zero.middle;

import com.netflix.hystrix.HystrixCommand;

/**
 * 封装一个模拟进行远程调用的 HystrixCommand, 返回结果设计为 String 类型
 */
public class MockRemoteServiceCommandWithFallback extends HystrixCommand<String> {

    private MockRemoteService remoteService;

    public MockRemoteServiceCommandWithFallback(Setter config, MockRemoteService remoteService) {
        super(config);
        this.remoteService = remoteService;
    }

    @Override
    protected String run() throws Exception {
        return remoteService.execute();
    }
    // 注意此处实现了 fallback 机制,也就是如果所模拟的远程调用失败,
    // 则调用该方法而不是抛出 HystrixRuntimeException 异常
    @Override
    protected String getFallback() {
        return "FALLBACK";
    }
}

3. 测试运行定义的Hystrix Command

package tut.zero;

import tut.zero.middle.MockRemoteService;
import tut.zero.middle.MockRemoteServiceCommand;
import tut.zero.simple.CommandHelloWorld;
import com.netflix.hystrix.HystrixCommand;
import com.netflix.hystrix.HystrixCommandGroupKey;
import com.netflix.hystrix.HystrixCommandProperties;
import com.netflix.hystrix.HystrixThreadPoolProperties;
import com.netflix.hystrix.exception.HystrixRuntimeException;
import org.junit.Test;

import java.util.concurrent.Future;

import static org.hamcrest.CoreMatchers.equalTo;
import static org.junit.Assert.assertThat;

public class HystrixTest {    
    /**
     * 远程调用耗时超过了 HystrixCommand 所能容忍的时间限度,之后执行 fallback 机制
     */
    @Test
    public void testMockRemoteServiceCallWithFallback() {

        HystrixCommand.Setter config = HystrixCommand.Setter
                .withGroupKey(
                HystrixCommandGroupKey.Factory.asKey("设置可容忍的超时时间小于远程方法的执行时间"));

        HystrixCommandProperties.Setter commandProperties = HystrixCommandProperties.Setter();
        commandProperties.withExecutionTimeoutInMilliseconds(1_000);
        config.andCommandPropertiesDefaults(commandProperties);

        assertThat(
        	new MockRemoteServiceCommandWithFallback(config, new MockRemoteService(2_000)).execute(), 
	        equalTo("FALLBACK"));
    }      
}

该测试预期可以执行通过。远程调用设计为执行2秒,本地执行容忍超时设定为1秒,也就是说远程调用尚未结束,本地执行就失去耐心要超时了。但此时它并不抛出异常,因为我们在MockRemoteServiceCommandWithFallback实现了fallback机制,也就是其getFallback方法的实现,所以此时MockRemoteServiceCommandWithFallback在这种情况下会返回FALLBACK,而不是抛出异常。

猜你喜欢

转载自blog.csdn.net/andy_zhang2007/article/details/88380456