赞
踩
在分布式系统中,难免有对外部接口的依赖,而外部接口有可能出现响应缓慢,大量请求超时,大量访问出现异常等情况。出现上面所说的情况有可能是由很多原因导制的,可能是网络抖动,外部系统有没有测出的bug,系统遭遇黑客攻击等。因为一个接口的异常,有可能导制线程阻塞,影响到其它接口的服务,甚至整个系统的服务给拖跨,对外部系统依赖的模块越多,出现的风险也就会越高,Hystrix正是用于解决这样的问题。Hystrix同样是Netflix公司开源的用于解决分布式问题而开源的框架。源码网址为:https://github.com/Netflix/Hystrix。Hystrix提供了如下几种解决方案应对上面说的问题,分别为:
- <dependencies>
- <dependency>
- <groupId>com.netflix.hystrix</groupId>
- <artifactId>hystrix-core</artifactId>
- <version>1.5.13</version>
- </dependency>
- </dependencies>
- package com.ivan.client.hystrix;
-
- import com.netflix.hystrix.HystrixCommand;
- import com.netflix.hystrix.HystrixCommandGroupKey;
-
- public class HelloCommand extends HystrixCommand<String> {
-
- protected HelloCommand() {
- super(HystrixCommandGroupKey.Factory.asKey("test"));
- }
-
- @Override
- protected String run() throws Exception {
- //模拟请求外部接口需要的时间长度
- Thread.sleep(500);
- return "sucess";
- }
-
- @Override
- protected String getFallback() {
- //当外部请求超时后,会执行fallback里的业务逻辑
- System.out.println("执行了回退方法");
- return "error";
- }
-
- }
- package com.ivan.client.hystrix;
-
- public class App {
- public static void main(String[] args) {
- HelloCommand command = new HelloCommand();
- String result = command.execute();
- System.out.println(result);
- }
- }
当我们增大 HelloCommand run方法里Thread.sleep()方法的时长时,我们可以看到 command.execute()方法调用返回了error。在实际的使用中,当发现第三方接口调用不通的情况下,会调用fallback方法进行降级处理,比如可以返回一段错误提示。
在分布式的系统里,系统可能对多个外部系统都有依赖关系,比同订单系统同时对会员系统,库存系统统,优惠券系统都有依赖。假如优惠券系统出现访问异常的时候,会超成线程的堆积,对于系统调用库存系统与会员系统的业务也不可用。而通过线程池能够将不同的业务由不同的线程池处理,从而做到保护其它业务能够正常访问。下面就来看看Hystrix是根据什么来创建线程的。
- /**
- 这个方法是AbstractCommand的构造方法,里面用于初使化AbstractCommand,包括circuitBreaker 与线程池对象都在这里进行构造
- **/
- protected AbstractCommand(HystrixCommandGroupKey group, HystrixCommandKey key, HystrixThreadPoolKey threadPoolKey, HystrixCircuitBreaker circuitBreaker, HystrixThreadPool threadPool,
- HystrixCommandProperties.Setter commandPropertiesDefaults, HystrixThreadPoolProperties.Setter threadPoolPropertiesDefaults,
- HystrixCommandMetrics metrics, TryableSemaphore fallbackSemaphore, TryableSemaphore executionSemaphore,
- HystrixPropertiesStrategy propertiesStrategy, HystrixCommandExecutionHook executionHook) {
- //commandGroup对象,用于组织一类业务相关的对象
- this.commandGroup = initGroupKey(group);
- // commandKey默认是以类为为名称的
- this.commandKey = initCommandKey(key, getClass());
- this.properties = initCommandProperties(this.commandKey, propertiesStrategy, commandPropertiesDefaults);
- //这个方法里定义了TheradPool里的关键字,默认以传入的commandGroup 的name做为key的名称
- this.threadPoolKey = initThreadPoolKey(threadPoolKey, this.commandGroup, this.properties.executionIsolationThreadPoolKeyOverride().get());
- this.metrics = initMetrics(metrics, this.commandGroup, this.threadPoolKey, this.commandKey, this.properties);
- this.circuitBreaker = initCircuitBreaker(this.properties.circuitBreakerEnabled().get(), circuitBreaker, this.commandGroup, this.commandKey, this.properties, this.metrics);
- //这里就是线程池对象啦。
- this.threadPool = initThreadPool(threadPool, this.threadPoolKey, threadPoolPropertiesDefaults);
-
- //Strategies from plugins
- this.eventNotifier = HystrixPlugins.getInstance().getEventNotifier();
- this.concurrencyStrategy = HystrixPlugins.getInstance().getConcurrencyStrategy();
- HystrixMetricsPublisherFactory.createOrRetrievePublisherForCommand(this.commandKey, this.commandGroup, this.metrics, this.circuitBreaker, this.properties);
- this.executionHook = initExecutionHook(executionHook);
-
- this.requestCache = HystrixRequestCache.getInstance(this.commandKey, this.concurrencyStrategy);
- this.currentRequestLog = initRequestLog(this.properties.requestLogEnabled().get(), this.concurrencyStrategy);
-
- /* fallback semaphore override if applicable */
- this.fallbackSemaphoreOverride = fallbackSemaphore;
-
- /* execution semaphore override if applicable */
- this.executionSemaphoreOverride = executionSemaphore;
- }
-
- /**
- 这个方法用于得到HystrixThreadPoolKey 对象, Hystrix内部有大量的Key对象,可以简单理解这些 Key都是相应对象的唯一标识。从代码里可以看出,默认情况下Hystrix采用的是commandGroup 的name做为Thread Pool的key值。
- **/
- private static HystrixThreadPoolKey initThreadPoolKey(HystrixThreadPoolKey threadPoolKey, HystrixCommandGroupKey groupKey, String threadPoolKeyOverride) {
- if (threadPoolKeyOverride == null) {
- // we don't have a property overriding the value so use either HystrixThreadPoolKey or HystrixCommandGroup
- if (threadPoolKey == null) {
- /* use HystrixCommandGroup if HystrixThreadPoolKey is null */
- return HystrixThreadPoolKey.Factory.asKey(groupKey.name());
- } else {
- return threadPoolKey;
- }
- } else {
- // we have a property defining the thread-pool so use it instead
- return HystrixThreadPoolKey.Factory.asKey(threadPoolKeyOverride);
- }
- }
-
- /**
- 在这里将调用具体的构造线程池的方法。
- **/
- private static HystrixThreadPool initThreadPool(HystrixThreadPool fromConstructor, HystrixThreadPoolKey threadPoolKey, HystrixThreadPoolProperties.Setter threadPoolPropertiesDefaults) {
- if (fromConstructor == null) {
- // get the default implementation of HystrixThreadPool
- return HystrixThreadPool.Factory.getInstance(threadPoolKey, threadPoolProperties
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。