Skip to content

Conversation

@trustin
Copy link
Member

@trustin trustin commented Nov 21, 2022

Motivation:

As a preparatory step for resolving #12842, we need a construct that limits concurrency asynchronously.

Modifications:

  • Add ConcurrencyLimit and ConcurrencyLimitHandler
  • Add the default implementation SimpleConcurrencyLimit

Result:

  • In our future work, we can allow a user to specify a ConcurrencyLimit when building a DnsNameResolver and use it for limiting the concurrency of DNS queries in DnsQueryContext.writeQuery()

Motivation:

As a preparatory step for resolving #12842, we need a construct that
limits concurrency asynchronously.

Modifications:

- Add `ConcurrencyLimit` and `ConcurrencyLimitHandler`
- Add the default implementation `SimpleConcurrencyLimit`

Result:

- In our future work, we can allow a user to specify a
  `ConcurrencyLimit` when building a `DnsNameResolver` and use it for
  limiting the concurrency of DNS queries in
  `DnsQueryContext.writeQuery()`
@trustin trustin added this to the 4.1.86.Final milestone Nov 21, 2022
@normanmaurer
Copy link
Member

@trustin welcome back buddy :)

Copy link
Contributor

@franz1981 franz1981 left a comment

Choose a reason for hiding this comment

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

I would allow using different queues types for pendingHandlers and would save the PendingHandler in a local variable outside of the CAS loop to reuse it in case of failing CAS.

Furthermore, not a blocker for this, I would implement a more constrained version (with lighter concurrent ops) for single threaded usage too (where it makes sense, to be used always by the same event loop)

assertEquals(expectedPermitsInUseOnAcquisition, limit.permitsInUse());
releaser.run();
assertEquals(expectedPermitsInUseOnAcquisition - 1, limit.permitsInUse());
events.add("acquired");
Copy link
Contributor

Choose a reason for hiding this comment

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

I think it'd be good if we declare class-level variables for event names.

Copy link
Member

@chrisvest chrisvest left a comment

Choose a reason for hiding this comment

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

Some comments

*
* @param releaser the {@link Runnable} that releases the permit
*/
void permitAcquired(Runnable releaser);
Copy link
Member

Choose a reason for hiding this comment

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

What's the idea behind relying on the callee to invoke the releaser, vs. automatically releasing a permit upon the completion of this method?

Comment on lines 92 to 93
pendingHandlers.add(pendingHandler);
return;
Copy link
Member

Choose a reason for hiding this comment

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

We have a data-race here where all permits could have been returned, and all releasers could have been called, before we manage to add our pending handler to the queue.

Comment on lines 117 to 118
pendingHandlers.add(pendingHandler);
return;
Copy link
Member

Choose a reason for hiding this comment

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

Same data-race exists here, with a smaller window.

assert nextPermitInUse >= 0 : "Released more than acquired";
if (permitsInUseUpdater.compareAndSet(SimpleConcurrencyLimit.this,
currentPermitInUse, nextPermitInUse)) {
final PendingHandler pendingHandler = pendingHandlers.poll();
Copy link
Member

Choose a reason for hiding this comment

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

If the pending handler is non-null, we could in theory "hand over" our existing permit, and skip the decrement/increment dance.

@trustin trustin marked this pull request as draft December 19, 2022 15:43
@trustin
Copy link
Member Author

trustin commented Dec 19, 2022

I renamed ConcurrencyLimit to Limiter and SimpleConcurrencyLimiter to ConcurrencyLimiter, and then added RateLimiter. I didn't address the comments yet and there are still some rough edges in the implementation, so I converted this PR to draft. I'll ping you once it's ready for reviews.

@trustin
Copy link
Member Author

trustin commented Jan 29, 2023

Had a chat with @normanmaurer a few days ago and we concluded that at the moment we don't really need any pluggability for rate-limiting DNS queries - just simple rate limiting implemented directly in our resolver implementation will do. Once we find similar use cases in other places in Netty, we may resurrect this PR, but for now, let me close it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants