Skip to content
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

rate-limiting: propagate back-pressure from queue as HTTP 429's #179

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

yaauie
Copy link
Contributor

@yaauie yaauie commented Oct 1, 2024

Adds a proactive handler that rejects new requests with HTTP 429's when the queue has been blocking for more than 10 consecutive seconds, allowing back- pressure to propagate in advance of filling up the connection backlog queue.

While I'd like to take the time to break out the supplied ExecutionObserver into a separate library, I think it is better to roll with what we have than to hold back.

Comment on lines 101 to 103
final boolean isCompact = execution.markComplete();
if (!isCompact) {
this.compactTail();
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

review note:

The Execution#markComplete() returns true iff marking the execution complete resulted in a node-level compaction. If it didn't, we try to compact from the tail.

Comment on lines 169 to 160
if (preCompletionNext != null) {
final Execution newNext = preCompletionNext.chaseTail();
return (newNext != preCompletionNext) && NEXT.compareAndSet(this, preCompletionNext, newNext);
}
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

review note:

We can't actually compact the completed node out, since we don't have a reference to its prev and a doubly-linked list is more complex than we need.

But we can fast-forward a newly-completed node's next pointer to the first node in the sequence that is either not yet completed or has no next, which may be a compaction that frees up memory and reduces future computation.

When we succeed at compacting, we return true so that the caller can make decisions about performing additional compactions.

Comment on lines 134 to 142
private static final java.lang.invoke.VarHandle NEXT;
static {
try {
MethodHandles.Lookup l = MethodHandles.lookup();
NEXT = l.findVarHandle(Execution.class, "next", Execution.class);
} catch (ReflectiveOperationException e) {
throw new ExceptionInInitializerError(e);
}
}
Copy link
Contributor Author

@yaauie yaauie Oct 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, this is Java 9+, so we would need to guard against it being installed in Logstash 7 (or rework to use AtomicReferences)

Comment on lines 18 to 19
private final AtomicReference<Execution> head; // newest execution
private final AtomicReference<Execution> tail; // oldest execution
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

TODO: invert to match java semantics, where things go into the tail (back) of a queue and are removed from the head (front)

Adds a proactive handler that rejects new requests with HTTP 429's when the
queue has been blocking for more than 10 consecutive seconds, allowing back-
pressure to propagate in advance of filling up the connection backlog queue.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants