This is the 14th day of my participation in Gwen Challenge

[a].

You may have a bad day, but that doesn’t mean you’ll have a bad life.

[Warm tips]

Continue from the previous article 🏹 “Hystrix” (2) parameter configuration details

  • I recommend it heremartinfowlerFuse introduction and authoritative guide, interested partners can study ha.

  • Main introduction related: official website description

  • about[How Hystrix works]The introduction of

[Background]

  • As the scale and complexity of distributed systems increase, the requirements for availability of distributed systems become higher and higher. Among the various high availability design patterns, “fuses, isolation, downgrades, limiting” are frequently used. The related technology, Hystrix itself is not a new technology, but it is the most classic technology system! .

  • Hystrix is designed to achieve fusible downgrades, thus improving system availability.

  • Hystrix is a Java service component library that implements circuit breaker mode and hatch mode on the call side to improve system fault tolerance by avoiding cascading failures for highly available designs.

  • Hystrix implements a resource isolation mechanism

The premise is introduced

Hystrix’s timeout detection is essentially done by starting a separate thread that executes exactly as long as the task has timed out, which is essentially a simple logic.

Hystrix times out and throws a HystrixTimeoutException.

Timeout detection logic

Hystrix timeouts include the registration process and the execution process. The registration process is as follows:

  • Perform lift (new HystrixObservableTimeoutOperator (_cmd) connection timeout detection task.

  • HystrixObservableTimeoutOperator class, the new TimerListener () is responsible for creating test task, Hystrixtimer.getinstance ().addtimerListener (listener) Associates scheduled tasks.

    • In HystrixObservableTimeoutOperator class, addTimerListener through Java timing task services scheduleAtFixedRate execution after the timeout time delay.

Hystrix’s timeout execution process is as follows:

  1. The tick method of class TimerListener is executed after the listener.tick() method is executed after the timeout

  2. Execute the HystrixContextRunnable run method after executing timeoutrunable.run () in the tick method of the TimerListener class

  3. Execute child.onError(new HystrixTimeoutException()) in the HystrixContextRunnable class run method to implement the timeout.

  4. executeCommandWithSpecifiedIsolation(_cmd).lift(new HystrixObservableTimeoutOperator(_cmd));

private static class HystrixObservableTimeoutOperator<R> implements Operator<R.R> {

        final AbstractCommand<R> originalCommand;

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

        @Override
        public Subscriber<? super R> call(final Subscriber<? super R> child) {
            final CompositeSubscription s = new CompositeSubscription();
            // if the child unsubscribes we unsubscribe our parent as well
            child.add(s);
            //capture the HystrixRequestContext upfront so that we can use it in the timeout thread later
            final HystrixRequestContext hystrixRequestContext = 
							HystrixRequestContext.getContextForCurrentThread();
            TimerListener listener = new TimerListener() {
                @Override
                public void tick(a) {
                  if(originalCommand.isCommandTimedOut
						.compareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.TIMED_OUT)) {
                        // report timeout failure
                        originalCommand.eventNotifier.markEvent(HystrixEventType.TIMEOUT, 
							originalCommand.commandKey);
                        // shut down the original request
                        s.unsubscribe();
                        final HystrixContextRunnable timeoutRunnable = new HystrixContextRunnable(
                                originalCommand.concurrencyStrategy, hystrixRequestContext, new Runnable() {
                            @Override
                            public void run(a) {
                                child.onError(newHystrixTimeoutException()); }}); timeoutRunnable.run(); }}@Override
                public int getIntervalTimeInMilliseconds(a) {
                    returnoriginalCommand.properties.executionTimeoutInMilliseconds().get(); }};final Reference<TimerListener> tl = HystrixTimer.getInstance().addTimerListener(listener);
            // set externally so execute/queue can see this
            originalCommand.timeoutTimer.set(tl);
            /** * If this subscriber receives values it means the parent succeeded/completed */
            Subscriber<R> parent = new Subscriber<R>() {
                @Override
                public void onCompleted(a) {
                    if (isNotTimedOut()) {
                        // stop timer and pass notification throughtl.clear(); child.onCompleted(); }}@Override
                public void onError(Throwable e) {
                    if (isNotTimedOut()) {
                        // stop timer and pass notification throughtl.clear(); child.onError(e); }}@Override
                public void onNext(R v) {
                    if(isNotTimedOut()) { child.onNext(v); }}private boolean isNotTimedOut(a) {
                    // if already marked COMPLETED (by onNext) or succeeds in setting to COMPLETED
                    returnoriginalCommand.isCommandTimedOut.get() == TimedOutStatus.COMPLETED || originalCommand.isCommandTimedOut.compareAndSet(TimedOutStatus.NOT_EXECUTED, TimedOutStatus.COMPLETED); }};// if s is unsubscribed we want to unsubscribe the parent
            s.add(parent);
            returnparent; }}public Reference<TimerListener> addTimerListener(final TimerListener listener) {
        startThreadIfNeeded();
        // add the listener
        Runnable r = new Runnable() {
            @Override
            public void run(a) {
                try {
                    listener.tick();
                } catch (Exception e) {
                    logger.error("Failed while ticking TimerListener", e); }}};// scheduleAtFixedRate takes the timeout period as a cycle to determine whether the execution is completeScheduledFuture<? > 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<Void> 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<Void>() {
            @Override
            public Void call(a) throws Exception {
                actual.run();
                return null; }});this.parentThreadState = hystrixRequestContext;
    }

    @Override
    public void run(a) {
        HystrixRequestContext existingState = HystrixRequestContext.getContextForCurrentThread();
        try {
            // set the state of this thread to that of its parent
            HystrixRequestContext.setContextOnCurrentThread(parentThreadState);
            // execute actual Callable with the state of the parent
            try {
                actual.call();
            } catch (Exception e) {
                throw newRuntimeException(e); }}finally {
            // restore this thread back to its original stateHystrixRequestContext.setContextOnCurrentThread(existingState); }}}Copy the code