-
-
Notifications
You must be signed in to change notification settings - Fork 9.6k
[RateLimiter] TokenBucket policy is not adding tokens if interval between requests is smaller than the interval provided in config #42627
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
Comments
Any news here? |
@relo-san If you can prepare a PR, that would be great. Thank you. |
Hey, thanks for your report! |
Hello? This issue is about to be closed if nobody replies. |
@AdamKatzDev I'm sorry to ask this on an issue but I couldn't figure out another way to contact you. |
…h a predefined frequency (relo-san) This PR was squashed before being merged into the 5.4 branch. Discussion ---------- [RateLimiter] TokenBucket policy fix for adding tokens with a predefined frequency | Q | A | ------------- | --- | Branch? | 5.4 | Bug fix? | yes | New feature? | no | Deprecations? | no | Tickets | Fix #42627 | License | MIT | Doc PR | symfony/symfony-docs#... <!-- required for new features --> Fixes bug, explained in issue #42627: when interval between requests smaller than rate interval, new tokens can not be added to bucket, because each request updates timer, and therefore rate interval never be reached. I replace this with approach where timer updates to time, when should have been last updated, and only when rate interval reached. I added test case for test adding tokens. As far as I see, there is no BC and no deprecations. There is method calculateNextTokenAvailability() on Symfony\Component\RateLimiter\Policy\Rate. It does not work correctly (does not match the name and the description), but as far as I can see, it is not used anywhere, so I left it unchanged. The Rate class simply cannot return this data, because it does not have a timer and does not know when the previous addition was made and, accordingly, what to calculate the next from. Commits ------- 7c8b6ed [RateLimiter] TokenBucket policy fix for adding tokens with a predefined frequency
Symfony version(s) affected: tested on 5.2, but seems that this is not fixed in any newer verison (5.3, 5.4, 6.0).
Description
TokenBucket policy is not adding tokens if the interval between requests is smaller than the interval provided in config.
How to reproduce
Basic configuration is sufficient. Storage type doesn't matter. It does not matter if locks are configured or not.
Limit: 1200, Interval: 1 minute, Amount: 1200
If the interval between requests is less than 1 minute then the bucket is never getting replenished. You will get throttled eventually.
Limit: 1200, Interval: 1 seconds, Amount: 20
If the interval between requests is less than 1 second then the bucket won't get replenished.
If you make the requests a bit slower then you will see that the bucket is getting new tokens.
Possible Solution
No suggestions so far but I've tracked the cause of this.
My theory is that after every successful consume request the policy writes it's execution timestamp to storage:
symfony/src/Symfony/Component/RateLimiter/Policy/TokenBucketLimiter.php
Lines 70 to 78 in 0cb1b5d
The next request uses the saved timestamp and current timestamp to add new tokens to the bucket:
symfony/src/Symfony/Component/RateLimiter/Policy/TokenBucket.php
Lines 68 to 73 in 0cb1b5d
symfony/src/Symfony/Component/RateLimiter/Policy/Rate.php
Lines 82 to 92 in 0cb1b5d
The
$cycles
variable will be 0 if$duration
is less than$this->refillTime
. If a user sets$this->refillTime
in hours or days then the algorithm is not usable at all. If$this->refillTime
is a few seconds then it can be somewhat usable in some conditions.Additional context


In the end we've moved to sliding window policy (the burst limit was the same as fill rate anyway) and it looks like this.
User that is limited to 120 requests per minute (exceeds usage, gets throttled frequently):
User that is limited to 1200 requests per minute (shouldn't be throttled at all):


The text was updated successfully, but these errors were encountered: