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

[vtadmin] cluster rpc pools #8421

Merged
merged 5 commits into from
Jul 7, 2021
Merged

Conversation

ajm188
Copy link
Contributor

@ajm188 ajm188 commented Jul 6, 2021

Description

This adds an RPCPool specialization on top of the generic pools.ResourcePool, and then adds several read pools (named this way so we don't need to rename (and rename the flags) when we add the r/w pools later). The main reason I'm not using sync2.Semaphore is because the timeout/context semantics don't work for our use case. With the semaphore, you can either use the semaphore's timeout or the context timeout, but what I want is to always use the minimum of the two. RPCPool does exactly that, plus we get all the stats/metrics of ResourcePool "for free".

From there, we add 4 rpc pools:

  • topoReadPool - for making general requests that end up reading from the topo, things like GetKeyspace, GetVSchema, etc
  • backupReadPool - for making requests that hit the backups endpoints, this is separate in case you need to control request rates to your backing store (s3, gcp, azure, etc)
  • schemaReadPool
  • workflowReadPool

Related Issue(s)

Checklist

  • Tests were added or are not required
  • Documentation was added or is not required

Deployment Notes

ajm188 added 5 commits July 6, 2021 11:16
An RPCPool is a special case of the ResourcePool, where the actual
"resources" in the pool are essentially a lease to perform an RPC (or
access any shared resource) with differing timeout semantics than the
sync2.Semaphore.

Signed-off-by: Andrew Mason <[email protected]>
We're about to get many more cases, so I'm simplifying it now.

Signed-off-by: Andrew Mason <[email protected]>
@ajm188 ajm188 added Type: Enhancement Logical improvement (somewhere between a bug and feature) Component: VTAdmin VTadmin interface labels Jul 6, 2021
@ajm188 ajm188 requested a review from doeg July 6, 2021 15:24
@ajm188 ajm188 requested a review from rohit-nayak-ps as a code owner July 6, 2021 15:24
Copy link
Contributor

@doeg doeg left a comment

Choose a reason for hiding this comment

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

Two questions but only one of them is quote-unquote blocking. 🌻

func (pool *RPCPool) Acquire(ctx context.Context) error {
if pool.waitTimeout > 0 {
var cancel context.CancelFunc
ctx, cancel = context.WithTimeout(ctx, pool.waitTimeout)
Copy link
Contributor

Choose a reason for hiding this comment

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

Does context.WithTimeout automatically respect the lesser of the given timeout or the ctx (first parameter)'s timeout? 🤔 I think I am missing something since the docs say:

// WithTimeout returns WithDeadline(parent, time.Now().Add(timeout)).

Copy link
Member

Choose a reason for hiding this comment

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

Yes, you can't extend a timeout in a context, only shorten it.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, it's in the docs for WithDeadline:

WithDeadline returns a copy of the parent context with the deadline adjusted to be no later than d. If the parent's deadline is already earlier than d, WithDeadline(parent, d) is semantically equivalent to parent.

Cells: cells,
})
c.topoReadPool.Release()
Copy link
Contributor

Choose a reason for hiding this comment

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

Non-blocking question -- in some cases, we use defer c.topoReadPool.Relase() and in others, like here, we Acquire and the Release sequentially (for lack of a better term).

In this case, it would be equivalent to defer, since it's the only Acquire/Release in the function, right? Is there much of a difference? (You've kinda sold me on the defer way since it seems easy (for me) to forget, otherwise, so I'm curious. 😈)

Copy link
Member

Choose a reason for hiding this comment

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

This is a general comment not directed at this specific usage. Until Go 1.14, defer had a significant penalty for hot paths, so you saw a lot of people avoiding it. That has mostly been eliminated, so except for rare circumstances, defer is the safer choice. IMO, it's easier to read, plus eliminates the possibility of adding a return somewhere without handling the unlock.
https://rakyll.org/inlined-defers/

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yeah, that's exactly the intent I had behind this. If we're just making the rpc, and moving the result from one struct to another (so no other function calls, or iterating over elements in a response, etc), then it's "fine" to just defer the release, but if we're going to do any other "meaningful" work (which i am loosely defining as function calls or iterations) then we should release immediately after finishing the rpc to free up other waiting goroutines.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ah somehow ... github did not show me Derek's comment. Derek's completely correct, but there's another consideration in that we are not just making the rpc call, so it doesn't make sense to be holding onto a slot in the pool for us to do unrelated work.

@ajm188 ajm188 merged commit ce77380 into vitessio:main Jul 7, 2021
@ajm188 ajm188 deleted the am_vtadmin_cluster_semas branch July 7, 2021 15:16
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Component: VTAdmin VTadmin interface Type: Enhancement Logical improvement (somewhere between a bug and feature)
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants