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

[TT-10749] New rate limiters (Leaky Bucket for 5.3) #5856

Merged
merged 29 commits into from
Jan 8, 2024

Conversation

titpetric
Copy link
Contributor

@titpetric titpetric commented Dec 8, 2023

This PR implements:

  • Leaky bucket rate limiter

The following rate limiter implementations are added behind a build tag -tags dev.

  • Token bucket rate limiter
  • Fixed window rate limiter
  • Sliding window rate limiter
  • Configurable storage for rate limiters

The Makefile/Dockerfile (uses make) and CI tests have been adjusted to include the dev tag.

https://tyktech.atlassian.net/browse/TT-10749

Copy link
Contributor

github-actions bot commented Dec 8, 2023

API Changes

--- prev.txt	2024-01-08 11:29:12.881178953 +0000
+++ current.txt	2024-01-08 11:29:09.637168090 +0000
@@ -4587,29 +4587,8 @@
 	// This is used as part of the RPC / Hybrid back-end configuration in a Tyk Enterprise installation and isn’t used anywhere else.
 	AuthOverride AuthOverrideConf `json:"auth_override"`
 
-	// Redis based rate limiter with fixed window. Provides 100% rate limiting accuracy, but require two additional Redis roundtrip for each request.
-	EnableRedisRollingLimiter bool `json:"enable_redis_rolling_limiter"`
-
-	// To enable, set to `true`. The sentinel-based rate limiter delivers a smoother performance curve as rate-limit calculations happen off-thread, but a stricter time-out based cool-down for clients. For example, when a throttling action is triggered, they are required to cool-down for the period of the rate limit.
-	// Disabling the sentinel based rate limiter will make rate-limit calculations happen on-thread and therefore offers a staggered cool-down and a smoother rate-limit experience for the client.
-	// For example, you can slow your connection throughput to regain entry into your rate limit. This is more of a “throttle” than a “block”.
-	// The standard rate limiter offers similar performance as the sentinel-based limiter. This is disabled by default.
-	EnableSentinelRateLimiter bool `json:"enable_sentinel_rate_limiter"`
-
-	// An enhancement for the Redis and Sentinel rate limiters, that offers a significant improvement in performance by not using transactions on Redis rate-limit buckets.
-	EnableNonTransactionalRateLimiter bool `json:"enable_non_transactional_rate_limiter"`
-
-	// How frequently a distributed rate limiter synchronises information between the Gateway nodes. Default: 2 seconds.
-	DRLNotificationFrequency int `json:"drl_notification_frequency"`
-
-	// A distributed rate limiter is inaccurate on small rate limits, and it will fallback to a Redis or Sentinel rate limiter on an individual user basis, if its rate limiter lower then threshold.
-	// A Rate limiter threshold calculated using the following formula: `rate_threshold = drl_threshold * number_of_gateways`.
-	// So you have 2 Gateways, and your threshold is set to 5, if a user rate limit is larger than 10, it will use the distributed rate limiter algorithm.
-	// Default: 5
-	DRLThreshold float64 `json:"drl_threshold"`
-
-	// Controls which algorthm to use as a fallback when your distributed rate limiter can't be used.
-	DRLEnableSentinelRateLimiter bool `json:"drl_enable_sentinel_rate_limiter"`
+	// RateLimit encapsulates rate limit configuration definitions.
+	RateLimit
 
 	// Allows you to dynamically configure analytics expiration on a per organisation level
 	EnforceOrgDataAge bool `json:"enforce_org_data_age"`
@@ -4928,7 +4907,11 @@
 	// ResourceSync configures mitigation strategy in case sync fails.
 	ResourceSync ResourceSyncConfig `json:"resource_sync"`
 
+	// Private contains configuration fields for internal app usage.
 	Private Private `json:"-"`
+
+	// DevelopmentConfig struct extends configuration for development builds.
+	DevelopmentConfig
 }
     Config is the configuration object used by Tyk to set up various parameters.
 
@@ -4936,10 +4919,18 @@
     New produces a new config object by parsing the default configuration for
     the values.
 
+func NewDefaultWithEnv() (*Config, error)
+    NewDefaultWithEnv gives a deep clone of the Default configuration and fills
+    it from environment provided.
+
 func (c Config) GetEventTriggers() map[apidef.TykEvent][]TykEventHandler
     GetEventTriggers returns event triggers. There was a typo in the json tag.
     To maintain backward compatibility, this solution is chosen.
 
+func (c *Config) GetRateLimiterStorage() *StorageOptionsConf
+    GetRateLimiterStorage will return the storage configuration to use for rate
+    limiters.
+
 func (c *Config) LoadIgnoredIPs()
 
 func (c *Config) SetEventTriggers(eventTriggers map[apidef.TykEvent][]TykEventHandler)
@@ -5007,6 +4998,9 @@
 	Tags []string `json:"tags"`
 }
 
+type DevelopmentConfig struct{}
+    DevelopmentConfig should contain no flags for official release builds.
+
 type DnsCacheConfig struct {
 	// Setting this value to `true` will enable caching of DNS queries responses used for API endpoint’s host names. By default caching is disabled.
 	Enabled bool `json:"enabled"`
@@ -5247,6 +5241,43 @@
 func (p Private) GetOAuthTokensPurgeInterval() time.Duration
     GetOAuthTokensPurgeInterval returns purge interval for lapsed OAuth tokens.
 
+type RateLimit struct {
+	// EnableLeakyBucketRateLimiter enables leaky bucket rate limiting.
+	//
+	// LeakyBucket will delay requests so they are processed in a FIFO
+	// style queue, ensuring a constant request rate and smoothing out
+	// traffic spikes. This comes at some cost to gateway instances, as
+	// the connections would be held for a longer time, instead of
+	// blocking the requests when they go over the defined rate limits.
+	EnableLeakyBucketRateLimiter bool `json:"enable_leaky_bucket_rate_limiter"`
+
+	// Redis based rate limiter with fixed window. Provides 100% rate limiting accuracy, but require two additional Redis roundtrip for each request.
+	EnableRedisRollingLimiter bool `json:"enable_redis_rolling_limiter"`
+
+	// To enable, set to `true`. The sentinel-based rate limiter delivers a smoother performance curve as rate-limit calculations happen off-thread, but a stricter time-out based cool-down for clients. For example, when a throttling action is triggered, they are required to cool-down for the period of the rate limit.
+	// Disabling the sentinel based rate limiter will make rate-limit calculations happen on-thread and therefore offers a staggered cool-down and a smoother rate-limit experience for the client.
+	// For example, you can slow your connection throughput to regain entry into your rate limit. This is more of a “throttle” than a “block”.
+	// The standard rate limiter offers similar performance as the sentinel-based limiter. This is disabled by default.
+	EnableSentinelRateLimiter bool `json:"enable_sentinel_rate_limiter"`
+
+	// An enhancement for the Redis and Sentinel rate limiters, that offers a significant improvement in performance by not using transactions on Redis rate-limit buckets.
+	EnableNonTransactionalRateLimiter bool `json:"enable_non_transactional_rate_limiter"`
+
+	// How frequently a distributed rate limiter synchronises information between the Gateway nodes. Default: 2 seconds.
+	DRLNotificationFrequency int `json:"drl_notification_frequency"`
+
+	// A distributed rate limiter is inaccurate on small rate limits, and it will fallback to a Redis or Sentinel rate limiter on an individual user basis, if its rate limiter lower then threshold.
+	// A Rate limiter threshold calculated using the following formula: `rate_threshold = drl_threshold * number_of_gateways`.
+	// So you have 2 Gateways, and your threshold is set to 5, if a user rate limit is larger than 10, it will use the distributed rate limiter algorithm.
+	// Default: 5
+	DRLThreshold float64 `json:"drl_threshold"`
+
+	// Controls which algorthm to use as a fallback when your distributed rate limiter can't be used.
+	DRLEnableSentinelRateLimiter bool `json:"drl_enable_sentinel_rate_limiter"`
+}
+    RateLimit contains flags and configuration for controlling rate limiting
+    behaviour. It is embedded in the main config structure.
+
 type Reporter struct {
 	// URL connection url to the zipkin server
 	URL        string `json:"url"`
@@ -9079,12 +9110,20 @@
     exclusively with user.SessionState objects, not identity
 
 type SessionLimiter struct {
-	Gw *Gateway `json:"-"`
 	// Has unexported fields.
 }
     SessionLimiter is the rate limiter for the API, use ForwardMessage() to
     check if a message should pass through or not
 
+func NewSessionLimiter(ctx context.Context, conf *config.Config, drlManager *drl.DRL) SessionLimiter
+    NewSessionLimiter initializes the session limiter.
+
+    The session limiter initializes the storage required for rate limiters.
+    It supports two storage types: `redis` and `local`. If redis storage is
+    configured, then redis will be used. If local storage is configured,
+    then in-memory counters will be used. If no storage is configured, it falls
+    back onto the default gateway storage configuration.
+
 func (l *SessionLimiter) Context() context.Context
 
 func (l *SessionLimiter) ForwardMessage(r *http.Request, currentSession *user.SessionState, key string, store storage.Handler, enableRL, enableQ bool, globalConf *config.Config, api *APISpec, dryRun bool) sessionFailReason

Copy link

sweep-ai bot commented Dec 8, 2023

Apply Sweep Rules to your PR?

  • Apply: All new business logic should have corresponding unit tests.
  • Apply: Refactor large functions to be more modular.
  • Apply: Add docstrings to all functions and file headers.

@buger
Copy link
Member

buger commented Dec 8, 2023

API tests result - postgres15-sha256 env: success
Branch used: refs/heads/master
Commit: d947e7a TT-10749 New rate limiters (Leaky Bucket for 5.3) (#5856)

This PR implements:

  • Leaky bucket rate limiter

The following rate limiter implementations are added behind a build tag
-tags dev.

  • Token bucket rate limiter
  • Fixed window rate limiter
  • Sliding window rate limiter
  • Configurable storage for rate limiters

The Makefile/Dockerfile (uses make) and CI tests have been adjusted to
include the dev tag.

https://tyktech.atlassian.net/browse/TT-10749


Co-authored-by: Tit Petric [email protected]
Triggered by: push (@titpetric)
Execution page

@buger
Copy link
Member

buger commented Dec 8, 2023

API tests result - postgres15-murmur64 env: success
Branch used: refs/heads/master
Commit: d947e7a TT-10749 New rate limiters (Leaky Bucket for 5.3) (#5856)

This PR implements:

  • Leaky bucket rate limiter

The following rate limiter implementations are added behind a build tag
-tags dev.

  • Token bucket rate limiter
  • Fixed window rate limiter
  • Sliding window rate limiter
  • Configurable storage for rate limiters

The Makefile/Dockerfile (uses make) and CI tests have been adjusted to
include the dev tag.

https://tyktech.atlassian.net/browse/TT-10749


Co-authored-by: Tit Petric [email protected]
Triggered by: push (@titpetric)
Execution page

@buger
Copy link
Member

buger commented Dec 8, 2023

API tests result - mongo44-sha256 env: success
Branch used: refs/heads/master
Commit: d947e7a TT-10749 New rate limiters (Leaky Bucket for 5.3) (#5856)

This PR implements:

  • Leaky bucket rate limiter

The following rate limiter implementations are added behind a build tag
-tags dev.

  • Token bucket rate limiter
  • Fixed window rate limiter
  • Sliding window rate limiter
  • Configurable storage for rate limiters

The Makefile/Dockerfile (uses make) and CI tests have been adjusted to
include the dev tag.

https://tyktech.atlassian.net/browse/TT-10749


Co-authored-by: Tit Petric [email protected]
Triggered by: push (@titpetric)
Execution page

@buger
Copy link
Member

buger commented Dec 8, 2023

API tests result - mongo44-murmur64 env: success
Branch used: refs/heads/master
Commit: d947e7a TT-10749 New rate limiters (Leaky Bucket for 5.3) (#5856)

This PR implements:

  • Leaky bucket rate limiter

The following rate limiter implementations are added behind a build tag
-tags dev.

  • Token bucket rate limiter
  • Fixed window rate limiter
  • Sliding window rate limiter
  • Configurable storage for rate limiters

The Makefile/Dockerfile (uses make) and CI tests have been adjusted to
include the dev tag.

https://tyktech.atlassian.net/browse/TT-10749


Co-authored-by: Tit Petric [email protected]
Triggered by: push (@titpetric)
Execution page

@titpetric titpetric changed the title POC: New rate limiters [TT-10749] POC: New rate limiters Dec 8, 2023
@titpetric titpetric changed the base branch from master to fix/tt-10838/fix-config-load-priority December 19, 2023 11:44
@titpetric titpetric force-pushed the poc/new-rate-limiters branch from 311e454 to e109821 Compare December 19, 2023 11:44
@titpetric titpetric force-pushed the fix/tt-10838/fix-config-load-priority branch 3 times, most recently from 84d830b to f3023e0 Compare December 20, 2023 10:48
@titpetric titpetric marked this pull request as ready for review December 20, 2023 11:02
@titpetric titpetric changed the title [TT-10749] POC: New rate limiters [TT-10749] New rate limiters Dec 20, 2023
@titpetric titpetric force-pushed the fix/tt-10838/fix-config-load-priority branch 4 times, most recently from 01b2a27 to f095185 Compare December 21, 2023 19:37
@titpetric titpetric changed the base branch from fix/tt-10838/fix-config-load-priority to master December 22, 2023 20:15
@titpetric titpetric force-pushed the poc/new-rate-limiters branch from 216ee43 to 94753cd Compare December 22, 2023 20:20
Copy link
Contributor

💥 CI tests failed 🙈

git-state

all ok

Please look at the run or in the Checks tab.

Copy link
Contributor

💥 CI tests failed 🙈

git-state

all ok

Please look at the run or in the Checks tab.

@buger
Copy link
Member

buger commented Dec 22, 2023

API tests result: failure 🚫
Branch used: refs/pull/5856/merge
Commit: 94753cd
Triggered by: pull_request (@titpetric)
Execution page

@buger
Copy link
Member

buger commented Dec 22, 2023

API tests result: failure 🚫
Branch used: refs/pull/5856/merge
Commit: d26114e
Triggered by: pull_request (@titpetric)
Execution page

@buger
Copy link
Member

buger commented Dec 22, 2023

API tests result: failure 🚫
Branch used: refs/pull/5856/merge
Commit: ea9079f
Triggered by: pull_request (@titpetric)
Execution page

@buger
Copy link
Member

buger commented Dec 22, 2023

API tests result: failure 🚫
Branch used: refs/pull/5856/merge
Commit: 9af2334
Triggered by: pull_request (@titpetric)
Execution page

@buger
Copy link
Member

buger commented Dec 22, 2023

API tests result: failure 🚫
Branch used: refs/pull/5856/merge
Commit: 634020c
Triggered by: pull_request (@titpetric)
Execution page

@buger
Copy link
Member

buger commented Dec 22, 2023

API tests result: failure 🚫
Branch used: refs/pull/5856/merge
Commit: 820adec
Triggered by: pull_request (@titpetric)
Execution page

@titpetric titpetric force-pushed the poc/new-rate-limiters branch from 9f4fb8d to 5e3c89e Compare December 22, 2023 21:47
@buger
Copy link
Member

buger commented Dec 22, 2023

API tests result: failure 🚫
Branch used: refs/pull/5856/merge
Commit: 9f4fb8d
Triggered by: pull_request (@titpetric)
Execution page

@titpetric titpetric force-pushed the poc/new-rate-limiters branch from cf00723 to 9787a43 Compare January 8, 2024 11:10
@TykTechnologies TykTechnologies deleted a comment from github-actions bot Jan 8, 2024
Copy link

sonarqubecloud bot commented Jan 8, 2024

Quality Gate Failed Quality Gate failed

Failed conditions

16.4% Coverage on New Code (required ≥ 80%)

See analysis details on SonarCloud

@titpetric titpetric changed the title [TT-10749] New rate limiters [TT-10749] New rate limiters (Leaky Bucket for 5.3) Jan 8, 2024
Copy link
Contributor

@jeffy-mathew jeffy-mathew left a comment

Choose a reason for hiding this comment

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

LGTM

@titpetric titpetric merged commit d947e7a into master Jan 8, 2024
19 of 20 checks passed
@titpetric titpetric deleted the poc/new-rate-limiters branch January 8, 2024 12:47
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.

5 participants