hystrix熔断 简介
在过去的几天里,我一直在探索Netflix Hystrix库,并欣赏了这个出色的库所提供的功能。
引用Hystrix网站上的内容:
Hystrix是一个延迟和容错库,旨在隔离对远程系统,服务和第三方库的访问点,停止级联故障,并在不可避免发生故障的复杂分布式系统中实现弹性。
这里有很多关键字可以解析,但是在我看来,体验Hystrix的最佳方法是尝试一个示例用例。
不可预测的服务
考虑一个服务,一个奇怪的服务,它接受具有以下结构的json消息并返回确认:
{"id":"1","payload": "Sample Payload","throw_exception":false,"delay_by": 0
}
该服务接收有效负载,但另外还接收两个字段:delay_by使服务在延迟(以毫秒为单位)后确认响应,而“ throw_exceptions”字段将在指定的延迟后导致异常!
这是一个示例响应:
{"id":"1","received":"Sample Payload","payload":"Reply Message"
}
如果您一直遵循,这是该示例的 github存储库, 本示例已使用Netflix Karyon 2 ,并且可以通过以下方式非常简洁地表达处理请求的代码–了解如何放置rx-java库在这里很好地利用:
import com.netflix.governator.annotations.Configuration;
import rx.Observable;
import service1.domain.Message;
import service1.domain.MessageAcknowledgement;import java.util.concurrent.TimeUnit;public class MessageHandlerServiceImpl implements MessageHandlerService {@Configuration("reply.message")private String replyMessage;public Observable<MessageAcknowledgement> handleMessage(Message message) {logger.info("About to Acknowledge");return Observable.timer(message.getDelayBy(), TimeUnit.MILLISECONDS).map(l -> message.isThrowException()).map(throwException -> {if (throwException) {throw new RuntimeException("Throwing an exception!");}return new MessageAcknowledgement(message.getId(), message.getPayload(), replyMessage);});}}
在这一点上,我们有一个很好的候选服务,可以使其响应任意延迟和失败。
服务的客户
现在转到此服务的客户端。 我正在使用Netflix Feign进行此调用,这是另一个很棒的库,它所需要的只是用以下方式注释的Java接口:
package aggregate.service;import aggregate.domain.Message;
import aggregate.domain.MessageAcknowledgement;
import feign.RequestLine;public interface RemoteCallService {@RequestLine("POST /message")MessageAcknowledgement handleMessage(Message message);
}
它使用以下几行的配置来创建实现此接口所需的代理:
RemoteCallService remoteCallService = Feign.builder().encoder(new JacksonEncoder()).decoder(new JacksonDecoder()).target(RemoteCallService.class, "http://127.0.0.1:8889");
我有多个终结点,这些终结点将呼叫委派给该远程客户端,所有这些终结点都沿以下方式显示url模式– http:// localhost:8888 / noHystrix?message = Hello&delay_by = 0&throw_exception = false ,第一个是终结点的示例不使用Hystrix。
没有Hystrix案例
作为第一个示例,如果我尝试调用http:// localhost:8888 / noHystrix?message = Hello&delay_by = 5000&throw_exception = false或说http:// localhost:8888 / ,请考虑在没有Hystrix的情况下调用Remote服务。 noHystrix?message = Hello&delay_by = 5000&throw_exception = true ,在这两种情况下,用户对端点的请求只会在响应之前挂起5秒钟。
这里应该立即显示一些事情:
- 如果服务响应缓慢,则客户端对服务的请求将被迫等待响应返回。
- 在高负载下,处理用户流量的所有线程很可能会用尽,从而使进一步的用户请求失败。
- 如果服务抛出异常,则客户端将无法正常处理该异常。
显然,需要像Hystrix这样的东西来处理所有这些问题。
Hystrix命令包装远程调用
我在前一个案例中使用了50个用户负载进行了一次小负载测试,结果如下:
================================================================================
---- Global Information --------------------------------------------------------
> request count 50 (OK=50 KO=0 )
> min response time 5007 (OK=5007 KO=- )
> max response time 34088 (OK=34088 KO=- )
> mean response time 17797 (OK=17797 KO=- )
> std deviation 8760 (OK=8760 KO=- )
> response time 50th percentile 19532 (OK=19532 KO=- )
> response time 75th percentile 24386 (OK=24386 KO=- )
> mean requests/sec 1.425 (OK=1.425 KO=- )
从服务中延迟5秒实质上会导致25秒的第75个百分位时间!,现在考虑使用Hystrix命令包装服务调用进行相同的测试:
================================================================================
---- Global Information --------------------------------------------------------
> request count 50 (OK=50 KO=0 )
> min response time 1 (OK=1 KO=- )
> max response time 1014 (OK=1014 KO=- )
> mean response time 22 (OK=22 KO=- )
> std deviation 141 (OK=141 KO=- )
> response time 50th percentile 2 (OK=2 KO=- )
> response time 75th percentile 2 (OK=2 KO=- )
> mean requests/sec 48.123 (OK=48.123 KO=- )
奇怪的是,现在第75个百分位数的时间是2毫秒!这是怎么可能的,使用Hystrix提供的出色工具,答案变得显而易见,这是此测试的Hystrix仪表板视图:
此处发生的情况是前10个请求超时,默认情况下使用Hystrix命令超时超过一秒,一旦前十个事务失败,Hystrix会将命令短路,从而阻止对远程服务的任何请求,因此低响应时间。 关于为什么这些事务未显示为失败的原因,是因为此处存在一个后备,当失败时该后备会优雅地响应用户请求。
结论
这样做的目的是为了阐明为什么需要一个像Hystrix这样的库的动机,在此之后,我将详细介绍将Hystrix集成到应用程序中所需要的内容以及这个出色的库提供的功能的广度。
翻译自: https://www.javacodegeeks.com/2015/10/gentle-introduction-to-hystrix.html
hystrix熔断 简介