Last active
February 3, 2022 10:47
-
-
Save bric3/2e6616c851614d2bd0fda330d24a6117 to your computer and use it in GitHub Desktop.
Exponential backoff counter implementing the Full Jitter algorithm from AWS article by Marc Brooker
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.util.Random; | |
/** | |
* Exponential backoff counter implementing the Full Jitter algorithm from <a href="https://aws.amazon.com/blogs/architecture/exponential-backoff-and-jitter/">aws</a> by Marc Brooker. | |
* | |
* <p> | |
* The idea of backoff is to introduce a delay between retries, so that client don't compete | |
* on the same resource. However it has been observed that clients may retry at the same time, | |
* thus clustering calls on the same resource. | |
* </p> | |
* <p> | |
* This algorithm e idea of this algorithm is to introduce some randomness (jitter) to the backoff, | |
* so that clients don't compete for the same resource at exactly the same time. | |
* </p> | |
* <p> | |
* From this article adding the jitter helps to spread the calls over the time, | |
* and more over helps to keep an approximate constant rate of calls. In other words | |
* it increases the overall throughput. | |
* </p> | |
* | |
* <p> | |
* So adding jitter to the backoff help is the reduction of failed attempts and thus | |
* reducing the overall work of the system, as such put less pressure o resources | |
* like the network itself. | |
* </p> | |
* | |
* <p> | |
* The article describes 3 jitter algorithms: | |
* <ol> | |
* <li>Full jitter: <pre><code> | |
* sleep = random(0, min(cap, base × 2 <sup>attempts</sup>)) | |
* </code></pre></li> | |
* <li>Equal jitter: <pre><code> | |
* temp = min(cap, base × 2 <sup>attempts</sup>) | |
* sleep = temp ÷ 2 + random(0, temp ÷ 2) | |
* </pre></code></li> | |
* <li>Decorrelated jitter: <pre><code> | |
* sleep = min(cap, random(base, previousSleep × 3)) | |
* </code></pre></li> | |
* </ol> | |
* Of the jitter approaches the <em>Equal jitter</em> is the loser, but it's | |
* less clear between <em>Decorrelated jitter</em> and <em>Full jitter</em>. | |
* <br> | |
* <strong>This implementation uses the <em>Full jitter</em> algorithm.</strong> | |
* </p> | |
* | |
* <p> | |
* This class is not thread safe. | |
* </p> | |
*/ | |
public final class ExponentialBackoff { | |
private final Random jitterRandom; | |
private final int baseMillis; | |
private final int capMillis; | |
private int previousAttempt = -1; | |
/** | |
* Creates a new capped exponential backoff timed counter. | |
* | |
* <p>Example waiting between 1s and 30s: | |
* <pre><code> | |
* var exponentialBackoff = new ExponentialBackoff(1_000, 30_000, new Random()); | |
* </code></pre> | |
* </p> | |
* | |
* @param baseMillis The minimum backoff time in milliseconds. | |
* @param capMillis The maximum backoff time in milliseconds. | |
* @param jitterRandom The jitterRandom source to use. | |
*/ | |
public ExponentialBackoff(final int baseMillis, final int capMillis, final Random jitterRandom) { | |
this.baseMillis = baseMillis; | |
this.capMillis = capMillis; | |
this.jitterRandom = jitterRandom; | |
} | |
/** | |
* Returns the backoff time in milliseconds. | |
* | |
* <p> | |
* Example: | |
* <pre><code> | |
* if (error) { | |
* var backoff = exponentialBackoff.backoffMillis(); | |
* Thread.sleep(backoff); // or instead of blocking schedule the task for later. | |
* } | |
* </code></pre> | |
* </p> | |
* | |
* @return The backoff time in milliseconds. | |
*/ | |
public int backoffMillis() { | |
previousAttempt += 1; | |
final int multiplier = (int) Math.pow(2, previousAttempt); | |
final int upper = Math.min(capMillis, baseMillis * multiplier); | |
return jitterRandom.nextInt(upper); | |
} | |
/** | |
* Resets the backoff for reuse. | |
*/ | |
public void reset() { | |
previousAttempt = -1; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment