[Hystrix Technical Guide] (3) The principle and implementation of the timeout mechanism

[One sentence per day]

Just because you had a bad day doesn't mean you'll have a bad life because of it.

[Background introduction]

  • The scale and complexity of distributed systems continue to increase, and with it comes higher and higher requirements for the availability of distributed systems. In various high-availability design patterns, [fusing, isolation, degradation, current limiting] are often used. As for related technologies, Hystrix itself is no longer considered a new technology, but it is the most classic technology system! .
  • Hystrix is ​​designed to achieve fuse degradation, thereby improving the availability of the system.
  • Hystrix is ​​a Java service component library that implements circuit breaker mode and compartment mode on the calling side, and improves system fault tolerance by avoiding cascading failures, thereby achieving high availability design.
  • * Hystrix implements resource isolation mechanism

Prerequisites

Hystrix's timeout detection is essentially detected by starting a separate thread. The execution time of the thread is exactly the time of the task timeout, which is essentially such a simple logic.

After Hystrix times out, a HystrixTimeoutException will be thrown .

timeout detection logic

Hystrix's timeout includes two registration processes and execution processes. The registration process is as follows:

  • Execute the timeout detection task associated with lift(new HystrixObservableTimeoutOperator(_cmd)) .
  • In the HystrixObservableTimeoutOperator class, new TimerListener() is responsible for creating detection tasks, and HystrixTimer.getInstance().addTimerListener(listener) is responsible for associating timing tasks .
    • In the HystrixObservableTimeoutOperator class, addTimerListener is executed after the delay timeout period through java's scheduled task service scheduleAtFixedRate .

Hystrix's timeout execution process is as follows:

  1. Execute the tick method of the class TimerListener after executing the listener.tick() method after the timeout
  2. Execute the run method of HystrixContextRunnable after executing timeoutRunnable.run() in the tick method of the TimerListener class
  3. Execute child.onError(new HystrixTimeoutException()) in the run method of the HystrixContextRunnable class to implement timeout .
  4. executeCommandWithSpecifiedIsolation(_cmd).lift(new HystrixObservableTimeoutOperator(_cmd));
private static class HystrixObservableTimeoutOperator implements Operator {
    
    

        final AbstractCommand originalCommand;

        public HystrixObservableTimeoutOperator(final AbstractCommand originalCommand) {
    
    
            this.originalCommand = originalCommand;
        }

        public Subscribersuper R> call(final Subscribersuper R> child) {
    
    
            final CompositeSubscription s = new CompositeSubscription();

            child.add(s);

            final HystrixRequestContext hystrixRequestContext =
							HystrixRequestContext.getContextForCurrentThread();
            TimerListener listener = new TimerListener() {
    
    

                public void tick() {
    
    
                  if(originalCommand.isCommandTimedOut
						.compareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.TIMED_OUT)) {
    
    

                        originalCommand.eventNotifier.markEvent(HystrixEventType.TIMEOUT,
							originalCommand.commandKey);

                        s.unsubscribe();
                        final HystrixContextRunnable timeoutRunnable = new HystrixContextRunnable(
                                originalCommand.concurrencyStrategy, hystrixRequestContext, new Runnable() {
    
    

                            public void run() {
    
    
                                child.onError(new HystrixTimeoutException());
                            }
                        });
                        timeoutRunnable.run();
                    }
                }

                public int getIntervalTimeInMilliseconds() {
    
    
                    return originalCommand.properties.executionTimeoutInMilliseconds().get();
                }
            };
            final Reference tl = HystrixTimer.getInstance().addTimerListener(listener);

            originalCommand.timeoutTimer.set(tl);

            Subscriber parent = new Subscriber() {
    
    

                public void onCompleted() {
    
    
                    if (isNotTimedOut()) {
    
    

                        tl.clear();
                        child.onCompleted();
                    }
                }

                public void onError(Throwable e) {
    
    
                    if (isNotTimedOut()) {
    
    

                        tl.clear();
                        child.onError(e);
                    }
                }

                public void onNext(R v) {
    
    
                    if (isNotTimedOut()) {
    
    
                        child.onNext(v);
                    }
                }
                private boolean isNotTimedOut() {
    
    

                    return originalCommand.isCommandTimedOut.get() == TimedOutStatus.COMPLETED ||
 				originalCommand.isCommandTimedOut.compareAndSet(TimedOutStatus.NOT_EXECUTED,
                                                                             TimedOutStatus.COMPLETED);
                }
            };

            s.add(parent);
            return parent;
        }
    }
    public Reference addTimerListener(final TimerListener listener) {
    
    
        startThreadIfNeeded();

        Runnable r = new Runnable() {
    
    

            public void run() {
    
    
                try {
    
    
                    listener.tick();
                } catch (Exception e) {
    
    
                    logger.error("Failed while ticking TimerListener", e);
                }
            }
        };

        ScheduledFuture f = executor.get().getThreadPool().scheduleAtFixedRate(r,
                listener.getIntervalTimeInMilliseconds(), listener.getIntervalTimeInMilliseconds(),
				TimeUnit.MILLISECONDS);
        	return new TimerReference(listener, f);
    }

	public class HystrixContextRunnable implements Runnable {
    
    
	    private final Callable actual;
    	private final HystrixRequestContext parentThreadState;
	    public HystrixContextRunnable(Runnable actual) {
    
    
    	    this(HystrixPlugins.getInstance().getConcurrencyStrategy(), actual);
    	}
	    public HystrixContextRunnable(HystrixConcurrencyStrategy concurrencyStrategy, final Runnable
			actual) {
    
    
        	this(concurrencyStrategy, HystrixRequestContext.getContextForCurrentThread(), actual);
    	}
	    public HystrixContextRunnable(final HystrixConcurrencyStrategy concurrencyStrategy,
                                  final HystrixRequestContext hystrixRequestContext, final Runnable actual) {
    
    
    	    this.actual = concurrencyStrategy.wrapCallable(new Callable() {
    
    

            public Void call() throws Exception {
    
    
                actual.run();
                return null;
            }

        });
        this.parentThreadState = hystrixRequestContext;
    }

    public void run() {
    
    
        HystrixRequestContext existingState = HystrixRequestContext.getContextForCurrentThread();
        try {
    
    

            HystrixRequestContext.setContextOnCurrentThread(parentThreadState);

            try {
    
    
                actual.call();
            } catch (Exception e) {
    
    
                throw new RuntimeException(e);
            }
        } finally {
    
    

            HystrixRequestContext.setContextOnCurrentThread(existingState);
        }
    }
}
复制代码

share resources

[External link picture transfer failed, the source site may have an anti-theft link mechanism, it is recommended to save the picture and upload it directly (img-2m51L4re-1691416305735)(https://pic.imgdb.cn/item/64d0dc6a1ddac507cc857b30.png)]Get the
above For resources, please visit the open source project and click to jump

Guess you like

Origin blog.csdn.net/star20100906/article/details/132155510