Armeria 的默认断路器实现是 NonBlockingCircuitBreaker,通过内部维护 State 用于状态切换。
canRequest 实现:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
@Override public boolean canRequest () { final State currentState = state.get (); if (currentState.isClosed ()) { // all requests are allowed during CLOSED return true; } else if (currentState.isHalfOpen () || currentState.isOpen ()) { if (currentState.checkTimeout () && state.compareAndSet (currentState, newHalfOpenState ())) { // changes to HALF_OPEN if OPEN state has timed out logStateTransition (CircuitState.HALF_OPEN, null); notifyStateChanged (CircuitState.HALF_OPEN); return true; } // all other requests are refused notifyRequestRejected (); return false; } return true; }
@Override public void onSuccess () { final State currentState = state.get (); if (currentState.isClosed ()) { // fires success event final Optional<EventCount> updatedCount = currentState.counter ().onSuccess (); // notifies the count if it has been updated updatedCount.ifPresent (this::notifyCountUpdated); } else if (currentState.isHalfOpen ()) { // changes to CLOSED if at least one request succeeds during HALF_OPEN if (state.compareAndSet (currentState, newClosedState ())) { logStateTransition (CircuitState.CLOSED, null); notifyStateChanged (CircuitState.CLOSED); } } }
@Override public void onFailure () { final State currentState = state.get (); if (currentState.isClosed ()) { // fires failure event final Optional<EventCount> updatedCount = currentState.counter ().onFailure (); // checks the count if it has been updated updatedCount.ifPresent (count -> { // changes to OPEN if failure rate exceeds the threshold if (checkIfExceedingFailureThreshold (count) && state.compareAndSet (currentState, newOpenState ())) { logStateTransition (CircuitState.OPEN, count); notifyStateChanged (CircuitState.OPEN); } else { notifyCountUpdated (count); } }); } else if (currentState.isHalfOpen ()) { // returns to OPEN if a request fails during HALF_OPEN if (state.compareAndSet (currentState, newOpenState ())) { logStateTransition (CircuitState.OPEN, null); notifyStateChanged (CircuitState.OPEN); } } }