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

fix(rate-limiting) removes race condition(redis) for better accuracy #8227

Conversation

giovanibrioni
Copy link
Contributor

@giovanibrioni giovanibrioni commented Dec 22, 2021

Summary

fix rate-limiting accuracy reported on issue: #5311

There is a low impact change to the current code and this implementation has better accuracy on redis policy

Full changelog

  • [it removes the race condition problem getting keys on redis. it uses the return of the increment command as the usage counter ensuring atomicity, different from the current one, which allows multiple requests to get the same value of the redis key while the counter increment is done asynchronously]

  • [it uses sliding window algorithm which is the most suitable for better accuracy]

  • [it works only with redis polity because redis is capable of guaranteeing atomicity and performance, which other polices could not guarantee]

  • [it maintains the current functioning and configuration of the plugin. the fixed window setting is the default to not impact routes already configured]

  • [it has an even better performance than the current plugin using the redis policy and fixed window, as it does only 1 operation per request in redis (eval) instead of the two operations per request that the current one (get and eval)]

Issues resolved

Fix #5311
KAG-981

Comment on lines +224 to +234
if current_usage and reset then
local remaining = max(0, limit - current_usage)
local stop = current_usage > limit
local headers
if not conf.hide_client_headers then
headers = {}

headers[RATELIMIT_LIMIT] = limit
headers[RATELIMIT_REMAINING] = remaining
headers[RATELIMIT_RESET] = reset
end

Choose a reason for hiding this comment

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

I think this is still a fixed window of time. The window is the TTL on a key, which never moves. So when the TTL expires after the fixed amount of time, the counter resets.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IMHO TTL is fixed but the window of time is not.
For example, if the time unit is 1 minute, fixed window counter guarantees an average rate in window [00:00, 00:01), [00:01,00:02), etc.
Suppose the limit is 10 per minute.
In fixed window if 10 requests arives at 00:00:59 and more 10 requests arives at 00:01:01 we have 20 alowed requests in the interval of 3 seconds.
With redis TTL it is not possible. At the same cenario only the first 10 requests are allowed. The last 10 recives 429 status code. The window limit slides between time window [00:00, 00:01) and [00:01,00:02)
But I'm open to suggestions

Copy link

Choose a reason for hiding this comment

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

I think you would have to keep timestamps of each request in a sorted set.
and on each request drop the timestamps between -inf and (now - window_time), add now. the count of items in the set is how many requests have been made in the window.
if the number is greater than the configured value, the limit has been reached

This would make the window sliding over the points in time as the requests are made.

@mikefero mikefero added the version-compatibility Incompatibility with older data plane versions label Apr 7, 2022
@hbagdi
Copy link
Member

hbagdi commented Mar 22, 2023

We have no plans to add a sliding window to this plugin. We can accept the improvements to Redis command used. Are you still up for adding support for that?

@esatterwhite
Copy link

We have no plans to add a sliding window to this plugin.

What's the reasoning here?

@hbagdi
Copy link
Member

hbagdi commented Mar 22, 2023

Sliding window is an enterprise-only feature at this point.

@esatterwhite
Copy link

Sliding window is an enterprise-only feature at this point.

Can we implement an algorithm that isn't a sliding window?

@hbagdi
Copy link
Member

hbagdi commented Mar 23, 2023

Can we implement an algorithm that isn't a sliding window?

Could you elaborate a bit?

@giovanibrioni
Copy link
Contributor Author

@hbagdi,
It's sad that the community can't implement the sliding window feature just because you decided it's an enterprise only feature.
But I can fix the race condition problem removing the sliding feature. Do you prefer I open a new PR or change this one?

@giovanibrioni
Copy link
Contributor Author

giovanibrioni commented Mar 25, 2023

@hbagdi, I sent the PR #10559 to fix the problem without sliding window feature.

@hbagdi hbagdi added the author/community PRs from the open-source community (not Kong Inc) label Mar 30, 2023
@locao
Copy link
Contributor

locao commented May 23, 2023

Closing in favor of #10559

@locao locao closed this May 23, 2023
ADD-SP pushed a commit that referenced this pull request May 31, 2023
it is same fix made in PR #8227, but I remove sliding-window feature.
Kong have no plans to add a sliding window to this plugin, Sliding window is an enterprise-only feature at this point
hanshuebner pushed a commit that referenced this pull request May 31, 2023
…g accuracy (#10559)

it is same fix made in PR #8227, but with the sliding-window feature removed.
Sliding window is an enterprise-only feature at this point

Co-authored-by: Chrono <chronolaw@gmail.com>
Co-authored-by: Qi <add_sp@outlook.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
author/community PRs from the open-source community (not Kong Inc) plugins/rate-limiting schema-change-noteworthy size/XL version-compatibility Incompatibility with older data plane versions
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Ratelimit plugin not working as expected - kong 1.4
7 participants