resilience4j
Consumer<T>
点击查看代码
package java.util.function;
import java.util.Objects;
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
default Consumer<T> andThen(Consumer<? super T> after) {
Objects.requireNonNull(after);
return (T t) -> { accept(t); after.accept(t); };
}
}
Callable<V>
点击查看代码
package java.util.concurrent;
@FunctionalInterface
public interface Callable<V> {
V call() throws Exception;
}
Supplier<T>
点击查看代码
package java.util.function;
@FunctionalInterface
public interface Supplier<T> {
T get();
}
Runnable
点击查看代码
package java.lang;
@FunctionalInterface
public interface Runnable {
public abstract void run();
}
Function<T, R>
点击查看代码
package java.util.function;
import java.util.Objects;
/**
* Represents a function that accepts one argument and produces a result.
*
* <p>This is a <a href="package-summary.html">functional interface</a>
* whose functional method is {@link #apply(Object)}.
*
* @param <T> the type of the input to the function
* @param <R> the type of the result of the function
*
* @since 1.8
*/
@FunctionalInterface
public interface Function<T, R> {
R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
Objects.requireNonNull(before);
return (V v) -> apply(before.apply(v));
}
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
Objects.requireNonNull(after);
return (T t) -> after.apply(apply(t));
}
static <T> Function<T, T> identity() {
return t -> t;
}
}
Future<V>
点击查看代码
package java.util.concurrent;
public interface Future<V> {
boolean cancel(boolean mayInterruptIfRunning);
boolean isCancelled();
boolean isDone();
V get() throws InterruptedException, ExecutionException;
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException;
}
Metrics 度量指标
点击查看代码
interface Metrics {
/**
* Returns the current failure rate in percentage. If the number of measured calls is below
* the minimum number of measured calls, it returns -1.
*
* @return the failure rate in percentage
*/
float getFailureRate();
/**
* Returns the current percentage of calls which were slower than a certain threshold. If
* the number of measured calls is below the minimum number of measured calls, it returns
* -1.
*
* @return the failure rate in percentage
*/
float getSlowCallRate();
/**
* Returns the current total number of calls which were slower than a certain threshold.
*
* @return the current total number of calls which were slower than a certain threshold
*/
int getNumberOfSlowCalls();
/**
* Returns the current number of successful calls which were slower than a certain
* threshold.
*
* @return the current number of successful calls which were slower than a certain threshold
*/
int getNumberOfSlowSuccessfulCalls();
/**
* Returns the current number of failed calls which were slower than a certain threshold.
*
* @return the current number of failed calls which were slower than a certain threshold
*/
int getNumberOfSlowFailedCalls();
/**
* Returns the current total number of buffered calls in the ring buffer.
*
* @return he current total number of buffered calls in the ring buffer
*/
int getNumberOfBufferedCalls();
/**
* Returns the current number of failed buffered calls in the ring buffer.
*
* @return the current number of failed buffered calls in the ring buffer
*/
int getNumberOfFailedCalls();
/**
* Returns the current number of not permitted calls, when the state is OPEN.
* <p>
* The number of denied calls is always 0, when the CircuitBreaker state is CLOSED or
* HALF_OPEN. The number of denied calls is only increased when the CircuitBreaker state is
* OPEN.
*
* @return the current number of not permitted calls
*/
long getNumberOfNotPermittedCalls();
/**
* Returns the current number of successful buffered calls in the ring buffer.
*
* @return the current number of successful buffered calls in the ring buffer
*/
int getNumberOfSuccessfulCalls();
}
CircuitBreakerMetrics
点击查看代码
package io.github.resilience4j.circuitbreaker.internal;
import io.github.resilience4j.circuitbreaker.CircuitBreaker;
import io.github.resilience4j.circuitbreaker.CircuitBreakerConfig;
import io.github.resilience4j.core.metrics.FixedSizeSlidingWindowMetrics;
import io.github.resilience4j.core.metrics.Metrics;
import io.github.resilience4j.core.metrics.SlidingTimeWindowMetrics;
import io.github.resilience4j.core.metrics.Snapshot;
import java.time.Clock;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.LongAdder;
import static io.github.resilience4j.core.metrics.Metrics.Outcome;
class CircuitBreakerMetrics implements CircuitBreaker.Metrics {
private final Metrics metrics;
private final float failureRateThreshold;
private final float slowCallRateThreshold;
private final long slowCallDurationThresholdInNanos;
private final LongAdder numberOfNotPermittedCalls;
private int minimumNumberOfCalls;
private CircuitBreakerMetrics(int slidingWindowSize,
CircuitBreakerConfig.SlidingWindowType slidingWindowType,
CircuitBreakerConfig circuitBreakerConfig,
Clock clock) {
if (slidingWindowType == CircuitBreakerConfig.SlidingWindowType.COUNT_BASED) {
this.metrics = new FixedSizeSlidingWindowMetrics(slidingWindowSize);
this.minimumNumberOfCalls = Math
.min(circuitBreakerConfig.getMinimumNumberOfCalls(), slidingWindowSize);
} else {
this.metrics = new SlidingTimeWindowMetrics(slidingWindowSize, clock);
this.minimumNumberOfCalls = circuitBreakerConfig.getMinimumNumberOfCalls();
}
this.failureRateThreshold = circuitBreakerConfig.getFailureRateThreshold();
this.slowCallRateThreshold = circuitBreakerConfig.getSlowCallRateThreshold();
this.slowCallDurationThresholdInNanos = circuitBreakerConfig.getSlowCallDurationThreshold()
.toNanos();
this.numberOfNotPermittedCalls = new LongAdder();
}
private CircuitBreakerMetrics(int slidingWindowSize,
CircuitBreakerConfig circuitBreakerConfig, Clock clock) {
this(slidingWindowSize, circuitBreakerConfig.getSlidingWindowType(), circuitBreakerConfig, clock);
}
static CircuitBreakerMetrics forClosed(CircuitBreakerConfig circuitBreakerConfig, Clock clock) {
return new CircuitBreakerMetrics(circuitBreakerConfig.getSlidingWindowSize(),
circuitBreakerConfig, clock);
}
static CircuitBreakerMetrics forHalfOpen(int permittedNumberOfCallsInHalfOpenState,
CircuitBreakerConfig circuitBreakerConfig, Clock clock) {
return new CircuitBreakerMetrics(permittedNumberOfCallsInHalfOpenState,
CircuitBreakerConfig.SlidingWindowType.COUNT_BASED, circuitBreakerConfig, clock);
}
static CircuitBreakerMetrics forForcedOpen(CircuitBreakerConfig circuitBreakerConfig, Clock clock) {
return new CircuitBreakerMetrics(0, CircuitBreakerConfig.SlidingWindowType.COUNT_BASED,
circuitBreakerConfig, clock);
}
static CircuitBreakerMetrics forDisabled(CircuitBreakerConfig circuitBreakerConfig, Clock clock) {
return new CircuitBreakerMetrics(0, CircuitBreakerConfig.SlidingWindowType.COUNT_BASED,
circuitBreakerConfig, clock);
}
static CircuitBreakerMetrics forMetricsOnly(CircuitBreakerConfig circuitBreakerConfig, Clock clock) {
return forClosed(circuitBreakerConfig, clock);
}
/**
* Records a call which was not permitted, because the CircuitBreaker state is OPEN.
*/
void onCallNotPermitted() {
numberOfNotPermittedCalls.increment();
}
/**
* Records a successful call and checks if the thresholds are exceeded.
*
* @return the result of the check
*/
public Result onSuccess(long duration, TimeUnit durationUnit) {
Snapshot snapshot;
if (durationUnit.toNanos(duration) > slowCallDurationThresholdInNanos) {
snapshot = metrics.record(duration, durationUnit, Outcome.SLOW_SUCCESS);
} else {
snapshot = metrics.record(duration, durationUnit, Outcome.SUCCESS);
}
return checkIfThresholdsExceeded(snapshot);
}
/**
* Records a failed call and checks if the thresholds are exceeded.
*
* @return the result of the check
*/
public Result onError(long duration, TimeUnit durationUnit) {
Snapshot snapshot;
if (durationUnit.toNanos(duration) > slowCallDurationThresholdInNanos) {
snapshot = metrics.record(duration, durationUnit, Outcome.SLOW_ERROR);
} else {
snapshot = metrics.record(duration, durationUnit, Outcome.ERROR);
}
return checkIfThresholdsExceeded(snapshot);
}
/**
* Checks if the failure rate is above the threshold or if the slow calls percentage is above
* the threshold.
*
* @param snapshot a metrics snapshot
* @return false, if the thresholds haven't been exceeded.
*/
private Result checkIfThresholdsExceeded(Snapshot snapshot) {
float failureRateInPercentage = getFailureRate(snapshot);
float slowCallsInPercentage = getSlowCallRate(snapshot);
if (failureRateInPercentage == -1 || slowCallsInPercentage == -1) {
return Result.BELOW_MINIMUM_CALLS_THRESHOLD;
}
if (failureRateInPercentage >= failureRateThreshold
&& slowCallsInPercentage >= slowCallRateThreshold) {
return Result.ABOVE_THRESHOLDS;
}
if (failureRateInPercentage >= failureRateThreshold) {
return Result.FAILURE_RATE_ABOVE_THRESHOLDS;
}
if (slowCallsInPercentage >= slowCallRateThreshold) {
return Result.SLOW_CALL_RATE_ABOVE_THRESHOLDS;
}
return Result.BELOW_THRESHOLDS;
}
private float getSlowCallRate(Snapshot snapshot) {
int bufferedCalls = snapshot.getTotalNumberOfCalls();
if (bufferedCalls == 0 || bufferedCalls < minimumNumberOfCalls) {
return -1.0f;
}
return snapshot.getSlowCallRate();
}
private float getFailureRate(Snapshot snapshot) {
int bufferedCalls = snapshot.getTotalNumberOfCalls();
if (bufferedCalls == 0 || bufferedCalls < minimumNumberOfCalls) {
return -1.0f;
}
return snapshot.getFailureRate();
}
/**
* {@inheritDoc}
*/
@Override
public float getFailureRate() {
return getFailureRate(metrics.getSnapshot());
}
/**
* {@inheritDoc}
*/
@Override
public float getSlowCallRate() {
return getSlowCallRate(metrics.getSnapshot());
}
/**
* {@inheritDoc}
*/
@Override
public int getNumberOfSuccessfulCalls() {
return this.metrics.getSnapshot().getNumberOfSuccessfulCalls();
}
/**
* {@inheritDoc}
*/
@Override
public int getNumberOfBufferedCalls() {
return this.metrics.getSnapshot().getTotalNumberOfCalls();
}
@Override
public int getNumberOfFailedCalls() {
return this.metrics.getSnapshot().getNumberOfFailedCalls();
}
@Override
public int getNumberOfSlowCalls() {
return this.metrics.getSnapshot().getTotalNumberOfSlowCalls();
}
@Override
public int getNumberOfSlowSuccessfulCalls() {
return this.metrics.getSnapshot().getNumberOfSlowSuccessfulCalls();
}
@Override
public int getNumberOfSlowFailedCalls() {
return this.metrics.getSnapshot().getNumberOfSlowFailedCalls();
}
/**
* {@inheritDoc}
*/
@Override
public long getNumberOfNotPermittedCalls() {
return this.numberOfNotPermittedCalls.sum();
}
enum Result {
BELOW_THRESHOLDS,
FAILURE_RATE_ABOVE_THRESHOLDS,
SLOW_CALL_RATE_ABOVE_THRESHOLDS,
ABOVE_THRESHOLDS,
BELOW_MINIMUM_CALLS_THRESHOLD;
public static boolean hasExceededThresholds(Result result) {
return hasFailureRateExceededThreshold(result) ||
hasSlowCallRateExceededThreshold(result);
}
public static boolean hasFailureRateExceededThreshold(Result result) {
return result == ABOVE_THRESHOLDS || result == FAILURE_RATE_ABOVE_THRESHOLDS;
}
public static boolean hasSlowCallRateExceededThreshold(Result result) {
return result == ABOVE_THRESHOLDS || result == SLOW_CALL_RATE_ABOVE_THRESHOLDS;
}
}
}