Class EventCountCircuitBreaker
- All Implemented Interfaces:
CircuitBreaker<Integer>
A circuit breaker can be used to protect an application against unreliable
services or unexpected load. A newly created EventCountCircuitBreaker
object is
initially in state closed meaning that no problem has been detected. When the
application encounters specific events (like errors or service timeouts), it tells the
circuit breaker to increment an internal counter. If the number of events reported in a
specific time interval exceeds a configurable threshold, the circuit breaker changes
into state open. This means that there is a problem with the associated sub
system; the application should no longer call it, but give it some time to settle down.
The circuit breaker can be configured to switch back to closed state after a
certain time frame if the number of events received goes below a threshold.
When a EventCountCircuitBreaker
object is constructed the following parameters
can be provided:
- A threshold for the number of events that causes a state transition to open state. If more events are received in the configured check interval, the circuit breaker switches to open state.
- The interval for checks whether the circuit breaker should open. So it is possible to specify something like "The circuit breaker should open if more than 10 errors are encountered in a minute."
- The same parameters can be specified for automatically closing the circuit breaker again, as in "If the number of requests goes down to 100 per minute, the circuit breaker should close itself again". Depending on the use case, it may make sense to use a slightly lower threshold for closing the circuit breaker than for opening it to avoid continuously flipping when the number of events received is close to the threshold.
This class supports the following typical use cases:
Protecting against load peaks
Imagine you have a server which can handle a certain number of requests per minute.
Suddenly, the number of requests increases significantly - maybe because a connected
partner system is going mad or due to a denial of service attack. A
EventCountCircuitBreaker
can be configured to stop the application from
processing requests when a sudden peak load is detected and to start request processing
again when things calm down. The following code fragment shows a typical example of
such a scenario. Here the EventCountCircuitBreaker
allows up to 1000 requests
per minute before it interferes. When the load goes down again to 800 requests per
second it switches back to state closed:
EventCountCircuitBreaker breaker = new EventCountCircuitBreaker(1000, 1, TimeUnit.MINUTE, 800); ... public void handleRequest(Request request) { if (breaker.incrementAndCheckState()) { // actually handle this request } else { // do something else, e.g. send an error code } }
Deal with an unreliable service
In this scenario, an application uses an external service which may fail from time to time. If there are too many errors, the service is considered down and should not be called for a while. This can be achieved using the following pattern - in this concrete example we accept up to 5 errors in 2 minutes; if this limit is reached, the service is given a rest time of 10 minutes:
EventCountCircuitBreaker breaker = new EventCountCircuitBreaker(5, 2, TimeUnit.MINUTE, 5, 10, TimeUnit.MINUTE); ... public void handleRequest(Request request) { if (breaker.checkState()) { try { service.doSomething(); } catch (ServiceException ex) { breaker.incrementAndCheckState(); } } else { // return an error code, use an alternative service, etc. } }
In addition to automatic state transitions, the state of a circuit breaker can be
changed manually using the methods open()
and close()
. It is also
possible to register PropertyChangeListener
objects that get notified whenever
a state transition occurs. This is useful, for instance to directly react on a freshly
detected error condition.
Implementation notes:
- This implementation uses non-blocking algorithms to update the internal counter and state. This should be pretty efficient if there is not too much contention.
- This implementation is not intended to operate as a high-precision timer in very short check intervals. It is deliberately kept simple to avoid complex and time-consuming state checks. It should work well in time intervals from a few seconds up to minutes and longer. If the intervals become too short, there might be race conditions causing spurious state transitions.
- The handling of check intervals is a bit simplistic. Therefore, there is no guarantee that the circuit breaker is triggered at a specific point in time; there may be some delay (less than a check interval).
- Since:
- 3.5
-
Nested Class Summary
Nested ClassesModifier and TypeClassDescriptionprivate static final class
An internally used data class holding information about the checks performed by this class.private static class
Internally used class for executing check logic based on the current state of the circuit breaker.private static final class
A specializedEventCountCircuitBreaker.StateStrategy
implementation for the state closed.private static final class
A specializedEventCountCircuitBreaker.StateStrategy
implementation for the state open.Nested classes/interfaces inherited from class org.apache.commons.lang3.concurrent.AbstractCircuitBreaker
AbstractCircuitBreaker.State
-
Field Summary
FieldsModifier and TypeFieldDescriptionprivate final AtomicReference
<EventCountCircuitBreaker.CheckIntervalData> Stores information about the current check interval.private final long
The time interval for closing the circuit breaker.private final int
The threshold for closing the circuit breaker.private final long
The time interval for opening the circuit breaker.private final int
The threshold for opening the circuit breaker.private static final Map
<AbstractCircuitBreaker.State, EventCountCircuitBreaker.StateStrategy> A map for accessing the strategy objects for the different states.Fields inherited from class org.apache.commons.lang3.concurrent.AbstractCircuitBreaker
PROPERTY_NAME, state
-
Constructor Summary
ConstructorsConstructorDescriptionEventCountCircuitBreaker
(int threshold, long checkInterval, TimeUnit checkUnit) Creates a new instance ofEventCountCircuitBreaker
which uses the same parameters for opening and closing checks.EventCountCircuitBreaker
(int openingThreshold, long checkInterval, TimeUnit checkUnit, int closingThreshold) Creates a new instance ofEventCountCircuitBreaker
with the same interval for opening and closing checks.EventCountCircuitBreaker
(int openingThreshold, long openingInterval, TimeUnit openingUnit, int closingThreshold, long closingInterval, TimeUnit closingUnit) Creates a new instance ofEventCountCircuitBreaker
and initializes all properties for opening and closing it based on threshold values for events occurring in specific intervals. -
Method Summary
Modifier and TypeMethodDescriptionprivate void
Changes the state of this circuit breaker and also initializes a newEventCountCircuitBreaker.CheckIntervalData
object.boolean
Checks the state of this circuit breaker and changes it if necessary.void
close()
Closes this circuit breaker.private static Map
<AbstractCircuitBreaker.State, EventCountCircuitBreaker.StateStrategy> Creates the map with strategy objects.long
Returns the interval (in nanoseconds) for checking for the closing threshold.int
Returns the threshold value for closing the circuit breaker.long
Returns the interval (in nanoseconds) for checking for the opening threshold.int
Returns the threshold value for opening the circuit breaker.boolean
Increments the monitored value by 1 and performs a check of the current state of this circuit breaker.boolean
incrementAndCheckState
(Integer increment) Increments the monitored value and performs a check of the current state of this circuit breaker.(package private) long
nanoTime()
Returns the current time in nanoseconds.nextCheckIntervalData
(int increment, EventCountCircuitBreaker.CheckIntervalData currentData, AbstractCircuitBreaker.State currentState, long time) Calculates the nextEventCountCircuitBreaker.CheckIntervalData
object based on the current data and the current state.void
open()
Opens this circuit breaker.private boolean
performStateCheck
(int increment) Actually checks the state of this circuit breaker and executes a state transition if necessary.private static EventCountCircuitBreaker.StateStrategy
Returns theEventCountCircuitBreaker.StateStrategy
object responsible for the given state.private boolean
updateCheckIntervalData
(EventCountCircuitBreaker.CheckIntervalData currentData, EventCountCircuitBreaker.CheckIntervalData nextData) Updates theEventCountCircuitBreaker.CheckIntervalData
object.Methods inherited from class org.apache.commons.lang3.concurrent.AbstractCircuitBreaker
addChangeListener, changeState, isClosed, isOpen, isOpen, removeChangeListener
-
Field Details
-
STRATEGY_MAP
private static final Map<AbstractCircuitBreaker.State,EventCountCircuitBreaker.StateStrategy> STRATEGY_MAPA map for accessing the strategy objects for the different states. -
checkIntervalData
Stores information about the current check interval. -
openingThreshold
private final int openingThresholdThe threshold for opening the circuit breaker. -
openingInterval
private final long openingIntervalThe time interval for opening the circuit breaker. -
closingThreshold
private final int closingThresholdThe threshold for closing the circuit breaker. -
closingInterval
private final long closingIntervalThe time interval for closing the circuit breaker.
-
-
Constructor Details
-
EventCountCircuitBreaker
Creates a new instance ofEventCountCircuitBreaker
which uses the same parameters for opening and closing checks.- Parameters:
threshold
- the threshold for changing the status of the circuit breaker; if the number of events received in a check interval is greater than this value, the circuit breaker is opened; if it is lower than this value, it is closed againcheckInterval
- the check interval for opening or closing the circuit breakercheckUnit
- theTimeUnit
defining the check interval
-
EventCountCircuitBreaker
public EventCountCircuitBreaker(int openingThreshold, long checkInterval, TimeUnit checkUnit, int closingThreshold) Creates a new instance ofEventCountCircuitBreaker
with the same interval for opening and closing checks.- Parameters:
openingThreshold
- the threshold for opening the circuit breaker; if this number of events is received in the time span determined by the check interval, the circuit breaker is openedcheckInterval
- the check interval for opening or closing the circuit breakercheckUnit
- theTimeUnit
defining the check intervalclosingThreshold
- the threshold for closing the circuit breaker; if the number of events received in the time span determined by the check interval goes below this threshold, the circuit breaker is closed again
-
EventCountCircuitBreaker
public EventCountCircuitBreaker(int openingThreshold, long openingInterval, TimeUnit openingUnit, int closingThreshold, long closingInterval, TimeUnit closingUnit) Creates a new instance ofEventCountCircuitBreaker
and initializes all properties for opening and closing it based on threshold values for events occurring in specific intervals.- Parameters:
openingThreshold
- the threshold for opening the circuit breaker; if this number of events is received in the time span determined by the opening interval, the circuit breaker is openedopeningInterval
- the interval for opening the circuit breakeropeningUnit
- theTimeUnit
defining the opening intervalclosingThreshold
- the threshold for closing the circuit breaker; if the number of events received in the time span determined by the closing interval goes below this threshold, the circuit breaker is closed againclosingInterval
- the interval for closing the circuit breakerclosingUnit
- theTimeUnit
defining the closing interval
-
-
Method Details
-
createStrategyMap
private static Map<AbstractCircuitBreaker.State,EventCountCircuitBreaker.StateStrategy> createStrategyMap()Creates the map with strategy objects. It allows access for a strategy for a given state.- Returns:
- the strategy map
-
stateStrategy
private static EventCountCircuitBreaker.StateStrategy stateStrategy(AbstractCircuitBreaker.State state) Returns theEventCountCircuitBreaker.StateStrategy
object responsible for the given state.- Parameters:
state
- the state- Returns:
- the corresponding
EventCountCircuitBreaker.StateStrategy
- Throws:
CircuitBreakingException
- if the strategy cannot be resolved
-
changeStateAndStartNewCheckInterval
Changes the state of this circuit breaker and also initializes a newEventCountCircuitBreaker.CheckIntervalData
object.- Parameters:
newState
- the new state to be set
-
checkState
public boolean checkState()Checks the state of this circuit breaker and changes it if necessary. The return value indicates whether the circuit breaker is now in state closed; a value of true typically means that the current operation can continue.This implementation checks the internal event counter against the threshold values and the check intervals. This may cause a state change of this circuit breaker.
- Specified by:
checkState
in interfaceCircuitBreaker<Integer>
- Specified by:
checkState
in classAbstractCircuitBreaker<Integer>
- Returns:
- true if the circuit breaker is now closed; false otherwise.
-
close
public void close()Closes this circuit breaker. Its state is changed to closed. If this circuit breaker is already closed, this method has no effect.A new check interval is started. If too many events are received in this interval, the circuit breaker changes again to state open. If this circuit breaker is already closed, this method has no effect, except that a new check interval is started.
- Specified by:
close
in interfaceCircuitBreaker<Integer>
- Overrides:
close
in classAbstractCircuitBreaker<Integer>
-
getClosingInterval
public long getClosingInterval()Returns the interval (in nanoseconds) for checking for the closing threshold.- Returns:
- the opening check interval
-
getClosingThreshold
public int getClosingThreshold()Returns the threshold value for closing the circuit breaker. If the number of events received in the time span determined by the closing interval goes below this threshold, the circuit breaker is closed again.- Returns:
- the closing threshold
-
getOpeningInterval
public long getOpeningInterval()Returns the interval (in nanoseconds) for checking for the opening threshold.- Returns:
- the opening check interval
-
getOpeningThreshold
public int getOpeningThreshold()Returns the threshold value for opening the circuit breaker. If this number of events is received in the time span determined by the opening interval, the circuit breaker is opened.- Returns:
- the opening threshold
-
incrementAndCheckState
public boolean incrementAndCheckState()Increments the monitored value by 1 and performs a check of the current state of this circuit breaker. This method works likecheckState()
, but the monitored value is incremented before the state check is performed.- Returns:
- true if the circuit breaker is now closed; false otherwise
-
incrementAndCheckState
Increments the monitored value and performs a check of the current state of this circuit breaker. This method works likeCircuitBreaker.checkState()
, but the monitored value is incremented before the state check is performed.- Specified by:
incrementAndCheckState
in interfaceCircuitBreaker<Integer>
- Specified by:
incrementAndCheckState
in classAbstractCircuitBreaker<Integer>
- Parameters:
increment
- value to increment in the monitored value of the circuit breaker- Returns:
- true if the circuit breaker is now closed; false otherwise
-
nanoTime
long nanoTime()Returns the current time in nanoseconds. This method is used to obtain the current time. This is needed to calculate the check intervals correctly.- Returns:
- the current time in nanoseconds
-
nextCheckIntervalData
private EventCountCircuitBreaker.CheckIntervalData nextCheckIntervalData(int increment, EventCountCircuitBreaker.CheckIntervalData currentData, AbstractCircuitBreaker.State currentState, long time) Calculates the nextEventCountCircuitBreaker.CheckIntervalData
object based on the current data and the current state. The next data object takes the counter increment and the current time into account.- Parameters:
increment
- the increment for the internal countercurrentData
- the current check data objectcurrentState
- the current state of the circuit breakertime
- the current time- Returns:
- the updated
EventCountCircuitBreaker.CheckIntervalData
object
-
open
public void open()Opens this circuit breaker. Its state is changed to open. Depending on a concrete implementation, it may close itself again if the monitored subsystem becomes available. If this circuit breaker is already open, this method has no effect.This circuit breaker may close itself again if the number of events received during a check interval goes below the closing threshold. If this circuit breaker is already open, this method has no effect, except that a new check interval is started.
- Specified by:
open
in interfaceCircuitBreaker<Integer>
- Overrides:
open
in classAbstractCircuitBreaker<Integer>
-
performStateCheck
private boolean performStateCheck(int increment) Actually checks the state of this circuit breaker and executes a state transition if necessary.- Parameters:
increment
- the increment for the internal counter- Returns:
- a flag whether the circuit breaker is now closed
-
updateCheckIntervalData
private boolean updateCheckIntervalData(EventCountCircuitBreaker.CheckIntervalData currentData, EventCountCircuitBreaker.CheckIntervalData nextData) Updates theEventCountCircuitBreaker.CheckIntervalData
object. The current data object is replaced by the one modified by the last check. The return value indicates whether this was successful. If it is false, another thread interfered, and the whole operation has to be redone.- Parameters:
currentData
- the current check data objectnextData
- the replacing check data object- Returns:
- a flag whether the update was successful
-