[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:
- Execute the tick method of the class TimerListener after executing the listener.tick() method after the timeout
- Execute the run method of HystrixContextRunnable after executing timeoutRunnable.run() in the tick method of the TimerListener class
- Execute child.onError(new HystrixTimeoutException()) in the run method of the HystrixContextRunnable class to implement timeout .
- 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