diff --git a/pom.xml b/pom.xml index 016dd4d..59bc3ff 100644 --- a/pom.xml +++ b/pom.xml @@ -5,6 +5,12 @@ 4.0.0 + + org.sonatype.oss + oss-parent + 7 + + org.zkybase kite 0.5.0-SNAPSHOT @@ -28,10 +34,9 @@ - git://github.com/williewheeler/kite.git - git@github.com:williewheeler/kite.git - HEAD - https://github.com/williewheeler/kite + scm:git:git://github.com/williewheeler/kite.git + scm:git:git@github.com:williewheeler/kite.git + git://github.com/williewheeler/kite.git diff --git a/src/main/java/org/zkybase/kite/AbstractGuard.java b/src/main/java/org/zkybase/kite/AbstractGuard.java index 6ee6604..e49bc26 100644 --- a/src/main/java/org/zkybase/kite/AbstractGuard.java +++ b/src/main/java/org/zkybase/kite/AbstractGuard.java @@ -19,6 +19,8 @@ import org.springframework.jmx.export.annotation.ManagedAttribute; /** + * Abstract base class for implementing guards. + * * @author Willie Wheeler (willie.wheeler@gmail.com) * @since 1.0 */ diff --git a/src/main/java/org/zkybase/kite/Guard.java b/src/main/java/org/zkybase/kite/Guard.java index cd79d92..ede97de 100644 --- a/src/main/java/org/zkybase/kite/Guard.java +++ b/src/main/java/org/zkybase/kite/Guard.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2010-2012 the original author or authors. + * Copyright (c) 2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. diff --git a/src/main/java/org/zkybase/kite/GuardCallback.java b/src/main/java/org/zkybase/kite/GuardCallback.java index f638a2a..9db5dd7 100644 --- a/src/main/java/org/zkybase/kite/GuardCallback.java +++ b/src/main/java/org/zkybase/kite/GuardCallback.java @@ -16,10 +16,16 @@ package org.zkybase.kite; /** + * Callback interface for the {@link Guard} template. + * * @author Willie Wheeler (willie.wheeler@gmail.com) * @since 1.0 */ public interface GuardCallback { + /** + * @return execution result + * @throws Exception if there's a problem executing the callback + */ T doInGuard() throws Exception; } diff --git a/src/main/java/org/zkybase/kite/guard/CircuitBreakerTemplate.java b/src/main/java/org/zkybase/kite/guard/CircuitBreakerTemplate.java index 551a2f1..0059cfa 100644 --- a/src/main/java/org/zkybase/kite/guard/CircuitBreakerTemplate.java +++ b/src/main/java/org/zkybase/kite/guard/CircuitBreakerTemplate.java @@ -15,6 +15,9 @@ */ package org.zkybase.kite.guard; +import static org.springframework.util.Assert.isTrue; +import static org.springframework.util.Assert.notNull; + import java.util.ArrayList; import java.util.List; import java.util.concurrent.atomic.AtomicInteger; @@ -24,37 +27,38 @@ import org.springframework.jmx.export.annotation.ManagedAttribute; import org.springframework.jmx.export.annotation.ManagedOperation; import org.springframework.jmx.export.annotation.ManagedResource; -import org.springframework.util.Assert; import org.zkybase.kite.AbstractGuard; import org.zkybase.kite.GuardCallback; import org.zkybase.kite.exception.CircuitOpenException; /** *

- * Template for circuit breakers, which are components designed to protect - * clients from broken services by preventing faults from propagating across - * integration points. + * Template for circuit breakers, which are components designed to protect clients from broken services by preventing + * faults from propagating across integration points. + *

+ *

+ * For example, suppose that we have a web application that calls a web service. If the web service is having a problem + * (e.g., severe latency or perhaps complete unavailability), we don't want this to create problems for the app. Instead + * we want to isolate the problem. *

*

- * For example, suppose that we have a web application that calls a web service. - * If the web service is having a problem (e.g., severe latency or perhaps - * complete unavailability), we don't want this to create problems for the app. - * Instead we want to isolate the problem. + * The circuit breaker allows us to do just this. We associate a circuit breaker with each integration point, and the + * breaker mediates calls from the client to the service. Under normal circumstances the breaker is in the closed state, + * and calls pass through to the service. If however there is a problem, then the breaker goes into the open state for + * some period of time. While the breaker is open, all attempts to call the service fail with a {@link + * CircuitOpenException}. Once the problem is resolved, the breaker returns to the closed state and normal operations + * resume. *

*

- * The circuit breaker allows us to do just this. We associate a circuit breaker - * with each integration point, and calls from the client to the service are - * mediated by the breaker. Under normal circumstances the breaker is in the - * closed state, and calls pass through to the service. If however there is a - * problem, then the breaker goes into the open state for some period of time. - * While the breaker is open, all attempts to call the service fail with a - * {@link CircuitOpenException}. Once the problem is resolved, the breaker - * returns to the closed state and normal operations resume. + * State transition diagram *

*

- * The circuit breaker pattern is described in detail in Michael Nygard's book, - * Release It! - * (Pragmatic). + * The circuit breaker pattern is described in detail in Michael Nygard's book, Release It! (Pragmatic). + *

+ *

+ * We expose this guard as a JMX MBean so it can be queried and manipulated in management contexts. You can, for + * example, use JMX to trip and reset breakers manually. *

* * @author Willie Wheeler (willie.wheeler@gmail.com) @@ -77,9 +81,7 @@ public enum State { CLOSED, OPEN, HALF_OPEN }; private final AtomicInteger exceptionCount = new AtomicInteger(); private volatile long retryTime = NO_SCHEDULED_RETRY; - public CircuitBreakerTemplate() { - handledExceptions.add(Exception.class); - } + public CircuitBreakerTemplate() { handledExceptions.add(Exception.class); } /** *

@@ -90,9 +92,7 @@ public CircuitBreakerTemplate() { * @return exception threshold for this breaker */ @ManagedAttribute(description = "Breaker trips when threshold is reached") - public int getExceptionThreshold() { - return exceptionThreshold; - } + public int getExceptionThreshold() { return exceptionThreshold; } /** *

@@ -112,7 +112,7 @@ public int getExceptionThreshold() { description = "Breaker trips when threshold is reached", defaultValue = "5") public void setExceptionThreshold(int threshold) { - Assert.isTrue(threshold >= 1, "threshold must be >= 1"); + isTrue(threshold >= 1, "threshold must be >= 1"); this.exceptionThreshold = threshold; } @@ -141,7 +141,7 @@ public void setExceptionThreshold(int threshold) { description = "Delay in ms before open breaker goes half-open", defaultValue = "30000") public void setTimeout(long timeout) { - Assert.isTrue(timeout >= 0L, "timeout must be >= 0"); + isTrue(timeout >= 0L, "timeout must be >= 0"); this.timeout = timeout; } @@ -150,7 +150,7 @@ public List> getHandledExceptions() { } public void setHandledExceptions(List> exceptions) { - Assert.notNull(exceptions, "handledExceptions can't be null"); + notNull(exceptions, "handledExceptions can't be null"); this.handledExceptions = exceptions; } diff --git a/src/main/java/org/zkybase/kite/guard/ConcurrencyThrottleTemplate.java b/src/main/java/org/zkybase/kite/guard/ConcurrencyThrottleTemplate.java index 04c76a4..f2838de 100644 --- a/src/main/java/org/zkybase/kite/guard/ConcurrencyThrottleTemplate.java +++ b/src/main/java/org/zkybase/kite/guard/ConcurrencyThrottleTemplate.java @@ -27,11 +27,14 @@ /** *

- * Template component that fails with an exception when a concurrency threshold is exceeded. + * Guard that fails with an exception when a concurrency threshold is exceeded. *

*

* Implementation is based on a counting semaphore. *

+ *

+ * We expose this guard as a JMX MBean so it can be queried and manipulated in management contexts. + *

* * @author Willie Wheeler (willie.wheeler@gmail.com) * @since 1.0 @@ -44,7 +47,9 @@ public class ConcurrencyThrottleTemplate extends AbstractGuard { private final Semaphore semaphore; /** - * @param limit + * Creates a concurrency throttle with the given limit. The throttle rejects requests in excess of the limit. + * + * @param limit concurrency limit * @throws IllegalArgumentException if limit < 1 */ public ConcurrencyThrottleTemplate(int limit) { diff --git a/src/main/java/org/zkybase/kite/guard/RateLimitingThrottleTemplate.java b/src/main/java/org/zkybase/kite/guard/RateLimitingThrottleTemplate.java index 1ab0447..090786d 100644 --- a/src/main/java/org/zkybase/kite/guard/RateLimitingThrottleTemplate.java +++ b/src/main/java/org/zkybase/kite/guard/RateLimitingThrottleTemplate.java @@ -1,3 +1,18 @@ +/* + * Copyright (c) 2012 the original author or authors. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.zkybase.kite.guard; import java.util.Map; @@ -22,7 +37,11 @@ * allow a range of options with respect to the time window. *

*

- * Note that all counts reset on the hour, as measured by the wall clock. + * Note that all counts reset on the hour, as measured by the wall clock. This allows us to avoid tracking individual + * client requests and their timestamps. + *

+ *

+ * We expose this guard as a JMX MBean so it can be queried and manipulated in management contexts. *

* * @author Willie Wheeler (willie.wheeler@gmail.com)