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

Add a clocked rate limiter #4591

Merged
merged 2 commits into from Sep 6, 2023
Merged

Add a clocked rate limiter #4591

merged 2 commits into from Sep 6, 2023

Conversation

MichaelSnowden
Copy link
Contributor

What changed?
Our RateLimiterImpl now uses a ClockedRateLimiter instead of a raw go rate limiter which does not accept a clock.

Why?
To make unit testing / time skipping easier in the future, and to add some test coverage.

How did you test it?
I added a bunch of unit tests for the ClockedRateLimiter.

Potential risks

  1. If I missed something, we could be using system time instead of the clock, and it would make downstream issues harder to debug
  2. If there's a bug here, we could end up with a fauly rate limiter which prevents any requests from going through
  3. The tests aren't exactly trivial, so it could introduce a maintenance burden

Is hotfix candidate?
No

@MichaelSnowden MichaelSnowden requested a review from a team as a code owner July 7, 2023 01:42
@yiminc yiminc requested review from yycptt and pdoerner July 12, 2023 04:27
common/quotas/clocked_rate_limiter.go Outdated Show resolved Hide resolved
common/quotas/clocked_rate_limiter.go Show resolved Hide resolved
common/quotas/clocked_rate_limiter.go Show resolved Hide resolved
common/quotas/clocked_rate_limiter.go Show resolved Hide resolved
common/quotas/rate_limiter_impl.go Show resolved Hide resolved
common/quotas/rate_limiter_impl.go Outdated Show resolved Hide resolved
// the original method uses time.Now(), and does not allow us to pass in a time.Time. Fortunately, it can be built on
// top of ReserveN. However, there are some optimizations that we can make.
func (l ClockedRateLimiter) WaitN(ctx context.Context, token int) error {
reservation := ClockedReservation{l.rateLimiter.ReserveN(l.clock.Now(), token), l.clock}
Copy link
Member

Choose a reason for hiding this comment

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

looks like this will do reservation & cancellation more often than the original impl (when token can't be get within the wait duration), so more likely run into golang/go#56924 this issue: keep doing reservation & cancellation result in effectively a lower rps limit (we saw that in prod before)

But I think the change is ok since the only way to avoid ^ issue is to only call Wait() with context that has no deadline, and it still holds for with this change. so I guess this comment is just FYI.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Tbh I don't fully understand this issue, but it looks like the Go maintainers closed it because it's working as intended?

@MichaelSnowden MichaelSnowden force-pushed the snowden/rate-limiter-clock branch 2 times, most recently from 2af5b93 to 380aaff Compare September 1, 2023 16:35
@MichaelSnowden MichaelSnowden merged commit dc0a55d into main Sep 6, 2023
10 checks passed
@MichaelSnowden MichaelSnowden deleted the snowden/rate-limiter-clock branch September 6, 2023 00:30
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.

None yet

3 participants