Hystrix简介–总结

这是其他两篇文章的后续文章– 动机 ,说明为什么在分布式系统中需要类似Hystrix的内容,以及Hystrix基本介绍

这将是我的Hystrix旅程的总结,其中包含各种属性的详细信息,可以对这些属性进行调整以更改Hystrix的行为,并涉及一些高级概念

调整Hystrix行为

Hystrix的配置在此Wiki中进行了解释,简要介绍了两个主要的组来控制Hystrix的属性,

  1. 命令属性
  2. ThreadPool属性

属性遵循Wiki中说明的优先顺序,这里我将重点介绍通过属性文件指定的属性。

对于示例命令,定义了以下方式:

public class HelloWorldCommand extends HystrixCommand<String> {

    private static final Logger logger = LoggerFactory.getLogger(HelloWorldCommand.class);

    private final String name;

    public HelloWorldCommand(String name) {
        super(HystrixCommandGroupKey.Factory.asKey("default"));
        this.name = name;
    }

    @Override
    protected String run() throws Exception {
        logger.info("HelloWorld Command Invoked");
        return "Hello " + name;
    }
}

可以调整的第一个行为是在线程池中执行命令还是与调用方(SEMAPHORE策略类型)执行线程相同。 如果执行在线程池中,则可以设置请求超时。

hystrix.command.HelloWorldCommand.execution.isolation.strategy=THREAD
hystrix.command.HelloWorldCommand.execution.isolation.thread.timeoutInMilliseconds=1000

第二种行为是断路器,它根据在滚动时间窗内收集的信息进行工作,这种方式进行配置,例如持续10秒:

hystrix.command.HelloWorldCommand.metrics.rollingStats.timeInMilliseconds=10000

在此窗口中,如果一定百分比的故障(例如50%)发生在请求阈值(例如10秒内发生20个故障),则电路断开,其配置如下所示:

hystrix.command.HelloWorldCommand.circuitBreaker.requestVolumeThreshold=20
hystrix.command.HelloWorldCommand.circuitBreaker.errorThresholdPercentage=50

电路断开后,它将保持这种状态并保持以下设置的时间,在这种情况下为5秒:

hystrix.command.HelloWorldCommand.circuitBreaker.sleepWindowInMilliseconds=5000

线程池设置是使用指定的组密钥控制的,在本示例中称为默认组密钥。 不过,也可以将特定的“线程池键”指定为构造函数的一部分。

hystrix.threadpool.default.coreSize=10
hystrix.threadpool.default.queueSizeRejectionThreshold=5

在这里,可以并行运行10个命令,而其他5个则保留在队列中,超过该队列将拒绝请求。

要求折叠

Tomaz Nurkiewicz在他的博客网站NoBlogDefFound中做了出色的解释请求折叠的工作 。 我的示例有些简化,请考虑以下情况,其中有很多请求要检索给定id的Person,方法如下:

public class PersonService {

    public Person findPerson(Integer id) {
        return new Person(id, "name : " + id);
    }

    public List<Person> findPeople(List<Integer> ids) {
        return ids
                .stream()
                .map(i -> new Person(i, "name : " + i))
                .collect(Collectors.toList());
    }
}

该服务以固定响应进行响应,但假定该调用是对远程数据存储的。 还可以看到,该服务实现了一个批处理方法,以在给定ID列表的情况下检索人员列表。

请求折叠是一项功能,它将一段时间内发生的多个用户请求批处理为一个这样的远程呼叫,然后将响应散发回用户。

可以通过以下方式定义获取一组ID并获取人员响应的hystrix命令:

public class PersonRequestCommand extends HystrixCommand<List<Person>>{

    private final List<Integer> ids;
    private final PersonService personService = new PersonService();
    private static final Logger logger = LoggerFactory.getLogger(PersonRequestCommand.class);

    public PersonRequestCommand(List<Integer> ids) {
        super(HystrixCommandGroupKey.Factory.asKey("default"));
        this.ids = ids;
    }

    @Override
    protected List<Person> run() throws Exception {
        logger.info("Retrieving details for : " + this.ids);
        return personService.findPeople(this.ids);
    }
}

到目前为止,非常简单,复杂的逻辑现在位于RequestCollapser中,如下所示:

package aggregate.commands.collapsed;

import com.netflix.hystrix.HystrixCollapser;
import com.netflix.hystrix.HystrixCollapserKey;
import com.netflix.hystrix.HystrixCollapserProperties;
import com.netflix.hystrix.HystrixCommand;

import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

public class PersonRequestCollapser extends HystrixCollapser<List<Person>, Person, Integer> {

    private final Integer id;
    public PersonRequestCollapser(Integer id) {
        super(Setter.
                withCollapserKey(HystrixCollapserKey.Factory.asKey("personRequestCollapser"))
                .andCollapserPropertiesDefaults(HystrixCollapserProperties.Setter().withTimerDelayInMilliseconds(2000)));
        this.id = id;
    }

    @Override
    public Integer getRequestArgument() {
        return this.id;
    }

    @Override
    protected HystrixCommand<List<Person>> createCommand(Collection<CollapsedRequest<Person, Integer>> collapsedRequests) {
        List<Integer> ids = collapsedRequests.stream().map(cr -> cr.getArgument()).collect(Collectors.toList());
        return new PersonRequestCommand(ids);
    }

    @Override
    protected void mapResponseToRequests(List<Person> batchResponse, Collection<CollapsedRequest<Person, Integer>> collapsedRequests) {
        Map<Integer, Person> personMap = batchResponse.stream().collect(Collectors.toMap(Person::getId, Function.identity()));

        for (CollapsedRequest<Person, Integer> cr: collapsedRequests) {
            cr.setResponse(personMap.get(cr.getArgument()));
        }
    }
}

这里发生了一些事情,首先,参数化类型签名中的类型指示响应的类型(List <Person>),调用方期望的响应类型(Person)和请求的请求类型(请求的ID)。人)。 然后有两种方法,一种创建批处理命令,第二种将响应映射回原始请求。

现在,从用户的角度来看,这没有多大变化,就好像对单个命令一样进行调用,并且Request Collapsing处理批处理,分派和映射回响应。 这是示例测试的样子:

@Test
public void testCollapse() throws Exception {
    HystrixRequestContext requestContext = HystrixRequestContext.initializeContext();

    logger.info("About to execute Collapsed command");
    List<Observable<Person>> result = new ArrayList<>();
    CountDownLatch cl = new CountDownLatch(1);
    for (int i = 1; i <= 100; i++) {
        result.add(new PersonRequestCollapser(i).observe());
    }

    Observable.merge(result).subscribe(p -> logger.info(p.toString())
            , t -> logger.error(t.getMessage(), t)
            , () -> cl.countDown());
    cl.await();
    logger.info("Completed executing Collapsed Command");
    requestContext.shutdown();
}

结论

Hystrix的功能远不止我在这里介绍的内容。 它确实是一个很棒的库,对于创建弹性系统至关重要。我已经开始欣赏设计这个出色的库所花费的大量思考过程。

翻译自: https://www.javacodegeeks.com/2015/11/gentle-introduction-to-hystrix-wrapup.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值