Skip to content

Refactor rate limiter#1118

Merged
wxing1292 merged 7 commits into
temporalio:masterfrom
wxing1292:throttler
Dec 23, 2020
Merged

Refactor rate limiter#1118
wxing1292 merged 7 commits into
temporalio:masterfrom
wxing1292:throttler

Conversation

@wxing1292

@wxing1292 wxing1292 commented Dec 19, 2020

Copy link
Copy Markdown
Contributor

What changed?

  • Make RateLimiter support burst
  • Make DynamicRateLimiter handles periodical refresh of rate / burst

Why?
Support burst for rate limiter & code refactoring

How did you test it?
Run existing tests

Potential risks
N/A

@wxing1292 wxing1292 requested a review from a team December 19, 2020 06:46
* Make RateLimiter support burst
* Make DynamicRateLimiter handles periodical refresh of rate / burst
@wxing1292 wxing1292 marked this pull request as ready for review December 21, 2020 22:13

@alexshtin alexshtin left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I like this change. Makes throttle code more clear.

Comment thread common/quotas/dynamic.go
Comment on lines +55 to +56
Load() float64
Store(rate float64)

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Probably Set and Get are better names here.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Does Get actually needed?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Probably Set and Get are better names here.

underlying impl is using load & store, plus atomic.StoreInt64

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

But this is abstraction which essentially provides a function which returns previously set value. Interface should not be bound to particular implementation.
Actually, do you really need these structs and interface? It seems just like one more layer of redirection w/o any logic.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Interface should not be bound to particular implementation.

yep, but seems that load and store is more common?
ref: https://golang.org/pkg/sync/atomic/#LoadInt32

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Actually, do you really need these structs and interface? It seems just like one more layer of redirection w/o any logic.

unfortunately, matching is using this

Comment thread common/quotas/dynamic_rate_limiter.go
Comment thread common/quotas/dynamic_rate_limiter.go
Comment thread common/quotas/rate_limiter.go Outdated
Comment on lines +92 to +93
rl.Lock()
defer rl.Unlock()

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Suggested change
rl.Lock()
defer rl.Unlock()
rl.RLock()
defer rl.RUnlock()

and same for Burst (otherwise why to use RWMutex?)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

change to mutex

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Why? RWMutex seems to suite better here.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

rw mutex is relatively slower, plus the use case is NOT multiple reader getting the rate & burst

Comment on lines +122 to +123
rateLimiter: quotas.NewDefaultIncomingDynamicRateLimiter(
func() float64 { return float64(config.RPS()) },

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

👍

Comment on lines +114 to +115
rateLimiter: quotas.NewDefaultIncomingDynamicRateLimiter(
func() float64 { return float64(config.RPS()) },

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Conceptual question: why do history and matching need throttler at all? Shouldn't throttling to be handled on FE only?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

each individual host / service need to do proper self protection (according to the current resource usage)

@alexshtin alexshtin Dec 23, 2020

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

But who can produce such load besides FE? Yes there is matching <-> history communication, but they are not user facing and probably shouldn't be throttled.

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

It would be great to add metric to see if history and matching throttles actually throttle.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

but they are not user facing and probably shouldn't be throttled.

then the host can be overloaded

Comment thread service/matching/matcher.go Outdated
@wxing1292 wxing1292 merged commit 86ac8dd into temporalio:master Dec 23, 2020
@wxing1292 wxing1292 deleted the throttler branch December 23, 2020 19:34
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