Skip to content

[improve][client] PIP-468: Make Backoff jitter configurable#25669

Merged
merlimat merged 4 commits intoapache:masterfrom
merlimat:wt/thirsty-roentgen-7a00e5
May 6, 2026
Merged

[improve][client] PIP-468: Make Backoff jitter configurable#25669
merlimat merged 4 commits intoapache:masterfrom
merlimat:wt/thirsty-roentgen-7a00e5

Conversation

@merlimat
Copy link
Copy Markdown
Contributor

@merlimat merlimat commented May 5, 2026

Motivation

The existing Backoff class always subtracts up to 10% jitter from the next delay, never adds, and skips jitter on the first invocation entirely (the result is clamped back up to initialDelay). When many clients restart together, the first reconnect attempt fires at the exact configured initial delay — defeating the point of jitter. The jitter percentage was also hard-coded.

Modifications

  • Backoff takes a configurable jitterPercent (default 10).
  • Jitter is applied symmetrically as ±jitterPercent/2: the underlying delay is multiplied by a uniform random factor in [1 − jitterPercent/200, 1 + jitterPercent/200).
  • Jitter is applied on every call, including the first. The previous Math.max(initial, …) clamp is removed; the returned value may now be slightly below initialDelay or slightly above maxBackoff.
  • BackoffPolicy (v5 client API) gains a jitterPercent field with a withJitter(double) helper. Existing factory methods seed the default jitter so callers are unaffected.

The new BackoffPolicy.jitterPercent is currently API-shape only: the connection-backoff path is still TODO'd in PulsarClientBuilderV5, and the redelivery-backoff path goes through MultiplierRedeliveryBackoff which has no jitter support. Wiring is left for a follow-up.

Verifying this change

This change added tests and can be verified as follows:

  • New unit tests in BackoffTest:
    • jitterIsAppliedSymmetricallyOnFirstCall — across 500 resets verifies values both above and below the base, all within [base · 0.9, base · 1.1] for jitterPercent=20.
    • jitterPercentZeroDisablesJitter — verifies the disable path returns the exact base.
    • negativeJitterIsRejected — validation.
  • Existing tests updated to set jitterPercent(0) for deterministic exponential-progression and mandatory-stop checks.

Does this pull request potentially affect one of the following parts:

  • The public API

org.apache.pulsar.common.util.Backoff and org.apache.pulsar.client.api.v5.config.BackoffPolicy gain new optional fields/builder methods. Existing callers are unaffected (defaults preserve the 10% magnitude, though the direction now spans ±5% instead of −10%).

Adds a jitterPercent parameter to Backoff (default 10%) and exposes it
on BackoffPolicy in the v5 client API. Jitter is now applied
symmetrically as +/- jitterPercent/2 around the base delay and applied
on the first call as well, instead of always shaving up to 10% off and
skipping the initial delay.
Comment thread pulsar-common/src/main/java/org/apache/pulsar/common/util/Backoff.java Outdated
Reject values above 100 in both Backoff.Builder and BackoffPolicy so
the jitter factor stays in a sensible range. Add a test for the upper
bound.
merlimat added 2 commits May 5, 2026 14:50
…-7a00e5

# Conflicts:
#	pulsar-client-api-v5/src/main/java/org/apache/pulsar/client/api/v5/config/BackoffPolicy.java
…lTest

next() now applies symmetric jitter on the first call, so it no longer
returns the configured initial value exactly. The test only cares about
configuration, so query the configured initial directly.
@merlimat merlimat merged commit ff67bb2 into apache:master May 6, 2026
116 of 121 checks passed
@merlimat merlimat deleted the wt/thirsty-roentgen-7a00e5 branch May 6, 2026 01:33
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants