Hystrix 学习 2 : 模拟远程调用成功/超时失败

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

本文是本人学习Hystrix总结的第二篇,通过一个例子程序学习使用Hystrix模拟一个远程调用,这里调整Hystrix的执行参数和远程调用的参数观察成功和超时发生时抛出异常的情况。本应用特征如下 :

  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

package tut.zero.middle;

import com.netflix.hystrix.HystrixCommand;

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

    private MockRemoteService remoteService;

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

    @Override
    protected String run() throws Exception {
        return remoteService.execute();
    }
}

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 模拟封装一个远程调用(远程调用运行耗时可以模拟调节)
     *
     */
    @Test
    public void testMockRemoteServiceCallSuccessUsingDefaultConfig() {
        // 使用缺省配置执行 HystrixCommand
        HystrixCommand.Setter config = HystrixCommand.Setter.
                withGroupKey(
                HystrixCommandGroupKey.Factory.asKey("默认可容忍的超时时间大于远程方法的执行时间"));

        // 模拟一个会耗时100毫秒的远程调用
        assertThat(new MockRemoteServiceCommand(config, new MockRemoteService(100)).execute(), 
        	equalTo("SUCCESS"));
    }    
    
    /**
     * 远程调用耗时超过了 HystrixCommand 所能容忍的时间限度,预期会抛出异常 HystrixRuntimeException
     *
     */
    @Test(expected = HystrixRuntimeException.class)
    public void testMockRemoteServiceCallButHRE() {

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

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

        new MockRemoteServiceCommand(config, new MockRemoteService(15_000)).execute();
    }
    
    /**
     * 远程调用耗时增加,但是 HystrixCommand 客户端执行允许超时时间更大,所以远程调用可以成功执行完成
     *
     */
    @Test
    public void testMockRemoteServiceCallSuccessUsingBiggerTimeout() {
        HystrixCommand.Setter config = HystrixCommand.Setter
                .withGroupKey(
                	HystrixCommandGroupKey.Factory.asKey("设置可容忍的超时时间大于远程方法的执行时间"));

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

        assertThat(new MockRemoteServiceCommand(config, new MockRemoteService(15_000)).execute(), 
        	equalTo("SUCCESS"));
    }    
}

这里进行了三个测试,这三个测试运行都应该执行通过。他们的测试点如下 :

  1. testMockRemoteServiceCallSuccessUsingDefaultConfig

    使用缺省配置执行远程调用,并且远程调用所耗时间不太长,为100毫秒,此耗时低于缺省配置中可容忍的远程调用超时设置,所以该由MockRemoteServiceCommand封装的远程调用会成功执行。

  2. testMockRemoteServiceCallButHRE

    执行配置设置可容忍的远程调用超时为5秒,但是远程调用所耗时间为15秒,所以该由MockRemoteServiceCommand封装的远程调用会抛出异常HystrixRuntimeException。但请注意,该异常是该测试预期之内的,所以该测试会通过(换句话讲,如果不抛出该异常,则该测试不能通过)。

  3. testMockRemoteServiceCallSuccessUsingBiggerTimeout

    远程调用所耗时间为15秒,但执行配置中设置可容忍的远程调用超时为20秒,所以即使远程调用耗时很长,由MockRemoteServiceCommand封装的远程调用仍然成功返回,不会抛出异常。

猜你喜欢

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