variableMap = HystrixRequestContext.getContextForCurrentThread().state;            // short-circuit the synchronized path below if we already have the value in the ConcurrentHashMap      LazyInitializer v = variableMap.get(this);      if (v != null) {          return (T) v.get();      }        // 省略一部分      ....}从代码可以看出get与set操作相对应,也是从线程相关的ConcurrentHashMap获取相应的值,从前序介绍我们也得知当前线程是Hystrix提供的线程池线程,与调用者线程不是同一个线程,那么这个业务关注的上下文信息还能正确的传递到Hystrix线程中吗?经过测试它确实「神奇」的正确传递了,那到底是怎么做到的呢?原来是Hystrix「默默」的帮我们做了,通过调试我们看到如下一段关键代码:123456789101112131415161718192021this.actual = action;    // 调用者线程HystrixRequestContext信息    this.parentThreadState = HystrixRequestContext.getContextForCurrentThread();      this.c = concurrencyStrategy.wrapCallable(new Callable() {          @Override        public Void call() throws Exception {            HystrixRequestContext existingState = HystrixRequestContext.getContextForCurrentThread();            try {                // 帮我们做了一步拷贝操作                HystrixRequestContext.setContextOnCurrentThread(parentThreadState);                // 开始真正的执行业务定义的方法,此时上下文信息已经一致了                actual.call();                return null;            } finally {                HystrixRequestContext.setContextOnCurrentThread(existingState);            }        }    });}在执行业务定义的HystrixCommand方法前,Hystrix封装的对象帮我们把调用者线程的上下文信息「拷贝」过来了,其实这个处理的思路有点类似于我们前一个插件HystrixConcurrencyStrategy。五、总结HystrixConcurrencyStrategy 和HystrixCommandExecutionHook两者插件方式大家可以根据实际情况去判定,如果确定不需要在fallback中关注上下文传递信息,那用前者就可以了,也很简便,但如果你想解决的更彻底点,那么用后一种方式就可以了。作者:vivo 官网商城开发团队
11-10 15:37
查看更多