Skip to content

Add Randomization Factor in ExponentialBackOff #34773

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
JoosJuliet opened this issue Apr 17, 2025 · 1 comment
Open

Add Randomization Factor in ExponentialBackOff #34773

JoosJuliet opened this issue Apr 17, 2025 · 1 comment
Labels
status: waiting-for-triage An issue we've not yet triaged or decided on

Comments

@JoosJuliet
Copy link

JoosJuliet commented Apr 17, 2025

hello

Use Case

Predictable retry intervals in microservices can lead to server overload during peak failures. Randomizing these intervals can mitigate such issues.

Current Solution

The existing ExponentialBackOff mechanism predictably increases intervals, which can exacerbate server load during concurrent retries.

Proposed Enhancement

Propose adding a randomizationFactor to ExponentialBackOff to allow interval fluctuations, enhancing load distribution and reducing server stress.

Benefits

  • Collision Reduction: Randomizing intervals reduces peak load times by avoiding simultaneous retries.
  • Load Smoothing: Helps even out the demands on backend services, enhancing overall system stability.
  • Greater Control: Allows for precise adjustments to backoff settings, accommodating diverse application environments.

Implementation

This enhancement is designed to be fully backward compatible.
Here is the proposed change to the ExponentialBackOff class:

package org.springframework.util.backoff;

import org.springframework.util.Assert;

public class ExponentialBackOff implements BackOff {

    // Existing fields...

    private double randomizationFactor = 0.0; // Default to no randomization

    // Existing constructors...

    public ExponentialBackOff(long initialInterval, double multiplier, double randomizationFactor) {
        checkMultiplier(multiplier);
        this.initialInterval = initialInterval;
        this.multiplier = multiplier;
        this.randomizationFactor = randomizationFactor;
    }

    // Getter and setter for randomizationFactor...

    private class ExponentialBackOffExecution implements BackOffExecution {

        // Existing fields and methods...

        private long applyRandomization(long interval) {
            double random = (1 - randomizationFactor) + Math.random() * 2 * randomizationFactor;
            return (long) (interval * random);
        }

        @Override
        public long nextBackOff() {
            long nextInterval = computeNextInterval();
            return applyRandomization(nextInterval);
        }
    }
}

test code

@Test
    void withRandomizationFactor() {
        ExponentialBackOff backOff = new ExponentialBackOff(1000L, 2.0, 0.5);
        BackOffExecution execution = backOff.start();
        long firstBackOff = execution.nextBackOff();
        long secondBackOff = execution.nextBackOff();

        // Check if the back off is within expected randomization range
        assertThat(firstBackOff).isBetween(500L, 1500L);
        assertThat(secondBackOff).isBetween(1000L, 3000L);
    }

    @Test
    void randomizationFactorBounds() {
        ExponentialBackOff backOff = new ExponentialBackOff();
        assertThatIllegalArgumentException().isThrownBy(() ->
                backOff.setRandomizationFactor(-0.1));
        assertThatIllegalArgumentException().isThrownBy(() ->
                backOff.setRandomizationFactor(1.1));
    }

    @Test
    void randomizationEffectiveness() {
        ExponentialBackOff backOff = new ExponentialBackOff(1000L, 2.0, 0.5);
        BackOffExecution execution = backOff.start();
        boolean different = false;
        long previous = execution.nextBackOff();
        for (int i = 0; i < 10; i++) {
            long next = execution.nextBackOff();
            if (previous != next) {
                different = true;
                break;
            }
            previous = next;
        }
        assertThat(different).isTrue();
    }
@JoosJuliet JoosJuliet changed the title Enhancement: Add Randomization Factor in ExponentialBackOff Add Randomization Factor in ExponentialBackOff Apr 17, 2025
@spring-projects-issues spring-projects-issues added the status: waiting-for-triage An issue we've not yet triaged or decided on label Apr 17, 2025
@artembilan
Copy link
Member

Looks like a duplication of: #22009.
We might still reconsider this for current state of things.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status: waiting-for-triage An issue we've not yet triaged or decided on
Projects
None yet
Development

No branches or pull requests

3 participants