-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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-12566/TT-12851] Add client endpoint rate limiter #6462
Conversation
API Changes --- prev.txt 2024-08-20 11:12:09.682883050 +0000
+++ current.txt 2024-08-20 11:12:06.410806673 +0000
@@ -8193,6 +8193,9 @@
DisableIntrospection bool `json:"disable_introspection"`
FieldAccessRights []user.FieldAccessDefinition `json:"field_access_rights"`
Limit *user.APILimit `json:"limit"`
+
+ // Endpoints contains endpoint rate limit settings.
+ Endpoints user.Endpoints `json:"endpoints,omitempty"`
}
func (d *DBAccessDefinition) ToRegularAD() user.AccessDefinition
@@ -12345,8 +12348,7 @@
TYPES
type APILimit struct {
- Rate float64 `json:"rate" msg:"rate"`
- Per float64 `json:"per" msg:"per"`
+ RateLimit
ThrottleInterval float64 `json:"throttle_interval" msg:"throttle_interval"`
ThrottleRetryLimit int `json:"throttle_retry_limit" msg:"throttle_retry_limit"`
MaxQueryDepth int `json:"max_query_depth" msg:"max_query_depth"`
@@ -12355,17 +12357,14 @@
QuotaRemaining int64 `json:"quota_remaining" msg:"quota_remaining"`
QuotaRenewalRate int64 `json:"quota_renewal_rate" msg:"quota_renewal_rate"`
SetBy string `json:"-" msg:"-"`
-
- // Smoothing contains rate limit smoothing settings.
- Smoothing *apidef.RateLimitSmoothing `json:"smoothing" bson:"smoothing"`
}
APILimit stores quota and rate limit on ACL level (per API)
-func (g *APILimit) Duration() time.Duration
- Duration returns the time between two allowed requests at the defined rate.
- It's used to decide which rate limit has a bigger allowance.
+func (a APILimit) Clone() *APILimit
+ Clone does a deepcopy of APILimit.
-func (limit APILimit) IsEmpty() bool
+func (a APILimit) IsEmpty() bool
+ IsEmpty checks if APILimit is empty.
type AccessDefinition struct {
APIName string `json:"api_name" msg:"api_name"`
@@ -12379,6 +12378,8 @@
DisableIntrospection bool `json:"disable_introspection" msg:"disable_introspection"`
AllowanceScope string `json:"allowance_scope" msg:"allowance_scope"`
+
+ Endpoints Endpoints `json:"endpoints,omitempty" msg:"endpoints,omitempty"`
}
AccessDefinition defines which versions of an API a key has access to NOTE:
when adding new fields it is required to map them from DBAccessDefinition in
@@ -12396,6 +12397,37 @@
Hash HashType `json:"hash_type" msg:"hash_type"`
}
+type Endpoint struct {
+ Path string `json:"path,omitempty" msg:"path"`
+ Methods EndpointMethods `json:"methods,omitempty" msg:"methods"`
+}
+ Endpoint holds the configuration for endpoint rate limiting.
+
+type EndpointMethod struct {
+ Name string `json:"name,omitempty" msg:"name,omitempty"`
+ Limit RateLimit `json:"limit,omitempty" msg:"limit,omitempty"`
+}
+ EndpointMethod holds the configuration on endpoint method level.
+
+type EndpointMethods []EndpointMethod
+ EndpointMethods is a collection of EndpointMethod.
+
+type EndpointRateLimitInfo struct {
+ // KeySuffix is the suffix to use for the storage key.
+ KeySuffix string
+ // Rate is the allowance.
+ Rate float64
+ // Per is the rate limiting interval.
+ Per float64
+}
+ EndpointRateLimitInfo holds the information to process endpoint rate limits.
+
+type Endpoints []Endpoint
+ Endpoints is a collection of Endpoint.
+
+func (es Endpoints) RateLimitInfo(method string, path string) (*EndpointRateLimitInfo, bool)
+ RateLimitInfo returns EndpointRateLimitInfo for endpoint rate limiting.
+
type FieldAccessDefinition struct {
TypeName string `json:"type_name" msg:"type_name"`
FieldName string `json:"field_name" msg:"field_name"`
@@ -12458,6 +12490,21 @@
PerAPI bool `bson:"per_api" json:"per_api"`
}
+type RateLimit struct {
+ // Rate is the allowed number of requests per interval.
+ Rate float64 `json:"rate" msg:"rate"`
+ // Per is the interval at which rate limit is enforced.
+ Per float64 `json:"per" msg:"per"`
+
+ // Smoothing contains rate limit smoothing settings.
+ Smoothing *apidef.RateLimitSmoothing `json:"smoothing,omitempty" bson:"smoothing,omitempty"`
+}
+ RateLimit holds rate limit configuration.
+
+func (r RateLimit) Duration() time.Duration
+ Duration returns the time between two allowed requests at the defined rate.
+ It's used to decide which rate limit has a bigger allowance.
+
type SessionState struct {
LastCheck int64 `json:"last_check" msg:"last_check"`
Allowance float64 `json:"allowance" msg:"allowance"` |
PR Reviewer Guide 🔍
|
PR Code Suggestions ✨
|
60fc512
to
1333903
Compare
e68f55d
to
d768ba4
Compare
e1c722e
to
d94223d
Compare
globalConf.RateLimit.EnableSentinelRateLimiter = true | ||
case "DRL": | ||
globalConf.RateLimit.DRLEnableSentinelRateLimiter = true | ||
case "NonTransactional": |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this block is missing fixed window rl, should be able to use the internal/rate api to:
- get a symbol that has a list of all these limiters (there's an enum around already, needs a slice if there isn't one already)
- provide something like rate.Enable(*config.Config, RateLimiter/string) error
try to be mindful what test code is useful, should some tests be shorter, should some logic be part of a particular internal package rather than a test helper
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
2541759
to
6fd3c38
Compare
20f049d
to
adcae95
Compare
6db944d
to
95866ca
Compare
7c03309
to
7151951
Compare
Quality Gate passedIssues Measures |
User description
Description
This PR adds endpoint level rate limiting to keys.
Merging this in policies would be added in a follow up PR.
Counter usage and increments would be as follows.
/API1/Endpoint1
,/API1/Endpoint2
and/API2/Endpoint1
(usingAPI1Endpoint1_Counter
,API1Endpoint2_Counter
,API2Endpoint1_Counter
),/API1
and/API3
(usingAPI1_Counter
,API3_Counter
), no per API limits specified forAPI2
Related Issue
parent: https://tyktech.atlassian.net/browse/TT-12566
subtask: https://tyktech.atlassian.net/browse/TT-12851
Motivation and Context
How This Has Been Tested
Screenshots (if appropriate)
Types of changes
Checklist
PR Type
Enhancement, Tests
Description
session_manager.go
.session.go
to handle endpoint-specific rate limits.Changes walkthrough 📝
mw_rate_limiting_test.go
Add and refactor tests for endpoint rate limiting
gateway/mw_rate_limiting_test.go
endpointRateLimitTestHelper
function for testing endpointrate limits.
session_manager_test.go
Add tests for endpoint rate limit info retrieval
gateway/session_manager_test.go
getEndpointRateLimitInfo
function.method.
session_manager.go
Implement endpoint-specific rate limiting logic
gateway/session_manager.go
flow.
http.go
Add support for setup functions in test cases
test/http.go
BeforeFn
in test cases to execute setup functionsbefore tests.
session.go
Add endpoint-specific rate limit structures and clone method
user/session.go
Clone
method toAPILimit
for deep copying.Endpoint
,EndpointMethod
, andEndpointMethodRateLimit
structs for endpoint-specific rate limits.
AccessDefinition
to includeEndpoints
.