================================== Controller ================================== ThreadService, Current thread id : 37 ThreadService, HystrixThreadLocal: userId:1 ThreadService, RequestContextHolder: userId:1 ================================= Service ================================== ThreadService, Current thread id : 37 ThreadService, HystrixThreadLocal: userId:1 ThreadService, RequestContextHolder: userId:1
可以看到, thread id 是一样的,userid 也是一样的,这说明了此时是使用一个线程进行调用。
Hystrix 分线程调用
在 Service 的实现类上增加 @HystrixCommand 注解,重启再次访问,查看可控制台输出如下:
1 2 3 4 5 6 7
================================== Controller ================================== ThreadService, Current thread id : 36 ThreadService, HystrixThreadLocal: userId:1 ThreadService, RequestContextHolder: userId:1 ================================= Service ================================== ThreadService, Current thread id : 60 ThreadService, HystrixThreadLocal: userId:1
并在 ThreadService, RequestContextHolder 的位置抛出如下异常:
1 2 3 4 5 6 7 8 9 10
java.lang.IllegalStateException: No thread-bound request found: Are you referring to request attributes outside of an actual web request, or processing a request outside of the originally receiving thread? If you are actually operating within a web request and still receive this message, your code is probably running outside of DispatcherServlet: In this case, use RequestContextListener or RequestContextFilter to expose the current request. at org.springframework.web.context.request.RequestContextHolder.currentRequestAttributes(RequestContextHolder.java:131) ~[spring-web-5.1.2.RELEASE.jar:5.1.2.RELEASE] at com.laiyy.gitee.hystrix.thread.springcloudhystrixthread.service.ThreadServiceImpl.getUser(ThreadServiceImpl.java:36) ~[classes/:na] at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:1.8.0_171] at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) ~[na:1.8.0_171] at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:1.8.0_171] at java.lang.reflect.Method.invoke(Method.java:498) ~[na:1.8.0_171] at com.netflix.hystrix.contrib.javanica.command.MethodExecutionAction.execute(MethodExecutionAction.java:116) ~[hystrix-javanica-1.5.12.jar:1.5.12] at com.netflix.hystrix.contrib.javanica.command.MethodExecutionAction.executeWithArgs(MethodExecutionAction.java:93) ~[hystrix-javanica-1.5.12.jar:1.5.12] ...
/** * Provides an opportunity to wrap/decorate a {@code Callable<T>} before execution. * <p> * This can be used to inject additional behavior such as copying of thread state (such as {@link ThreadLocal}). * <p> * <b>Default Implementation</b> * <p> * Pass-thru that does no wrapping. * * @param callable * {@code Callable<T>} to be executed via a {@link ThreadPoolExecutor} * @return {@code Callable<T>} either as a pass-thru or wrapping the one given */ public <T> Callable<T> wrapCallable(Callable<T> callable){ return callable; }
/** * Register a {@link HystrixConcurrencyStrategy} implementation as a global override of any injected or default implementations. * * @param impl * {@link HystrixConcurrencyStrategy} implementation * @throws IllegalStateException * // 如果多次调用或在初始化默认值之后(如果在尝试注册之前发生了使用) 会抛出异常 * if called more than once or after the default was initialized (if usage occurs before trying to register) */ publicvoidregisterConcurrencyStrategy(HystrixConcurrencyStrategy impl){ if (!concurrencyStrategy.compareAndSet(null, impl)) { thrownew IllegalStateException("Another strategy was already registered."); } }
/** * Used to wrap code that will execute potentially risky functionality (typically meaning a service call over the network) * with fault and latency tolerance, statistics and performance metrics capture, circuit breaker and bulkhead functionality. * This command is essentially a blocking command but provides an Observable facade if used with observe() * * @param <R> * the return type * * @ThreadSafe */ publicabstractclassHystrixCommand<R> extendsAbstractCommand<R> implementsHystrixExecutable<R>, HystrixInvokableInfo<R>, HystrixObservable<R> { }
/** * Used to wrap code that will execute potentially risky functionality (typically meaning a service call over the network) * with fault and latency tolerance, statistics and performance metrics capture, circuit breaker and bulkhead functionality. * This command should be used for a purely non-blocking call pattern. The caller of this command will be subscribed to the Observable<R> returned by the run() method. * * @param <R> * the return type * * @ThreadSafe */ publicabstractclassHystrixObservableCommand<R> extendsAbstractCommand<R> implementsHystrixObservable<R>, HystrixInvokableInfo<R> { }