From 1d7036a86bab4169aa7659d0f368f8f09d97ab21 Mon Sep 17 00:00:00 2001 From: "data-plane-api(CircleCI)" Date: Sun, 28 Jun 2020 23:50:38 +0000 Subject: [PATCH] Support dynamic limit override in ratelimit filter (#11770) Provides a way to specify dynamic rate limit override in the rate limit descriptor from static value or from dynamic metadata. New type, RateLimitUnit was created to share across config protocol and rate limit service protocol. A PR for the reference implementation of the rate limit service will follow after the API changes are discussed and accepted. Signed-off-by: Petr Pchelko Mirrored from https://github.com/envoyproxy/envoy @ 7ea1f24bd53522408d9bc55316dff9ed1701bc73 --- envoy/config/route/v3/route_components.proto | 24 +++++++++++++++ .../route/v4alpha/route_components.proto | 30 +++++++++++++++++++ envoy/extensions/common/ratelimit/v3/BUILD | 1 + .../common/ratelimit/v3/ratelimit.proto | 20 +++++++++++++ envoy/service/ratelimit/v3/rls.proto | 2 ++ envoy/type/v3/ratelimit_unit.proto | 30 +++++++++++++++++++ 6 files changed, 107 insertions(+) create mode 100644 envoy/type/v3/ratelimit_unit.proto diff --git a/envoy/config/route/v3/route_components.proto b/envoy/config/route/v3/route_components.proto index 2dcfd383..21afddba 100644 --- a/envoy/config/route/v3/route_components.proto +++ b/envoy/config/route/v3/route_components.proto @@ -1497,6 +1497,24 @@ message RateLimit { } } + message Override { + // Fetches the override from the dynamic metadata. + message DynamicMetadata { + // Metadata struct that defines the key and path to retrieve the struct value. + // The value must be a struct containing an integer "requests_per_unit" property + // and a "unit" property with a value parseable to :ref:`RateLimitUnit + // enum ` + type.metadata.v3.MetadataKey metadata_key = 1 [(validate.rules).message = {required: true}]; + } + + oneof override_specifier { + option (validate.required) = true; + + // Limit override from dynamic metadata. + DynamicMetadata dynamic_metadata = 1; + } + } + // Refers to the stage set in the filter. The rate limit configuration only // applies to filters with the same stage number. The default stage number is // 0. @@ -1516,6 +1534,12 @@ message RateLimit { // configuration. See :ref:`composing actions // ` for additional documentation. repeated Action actions = 3 [(validate.rules).repeated = {min_items: 1}]; + + // An optional limit override to be appended to the descriptor produced by this + // rate limit configuration. If the override value is invalid or cannot be resolved + // from metadata, no override is provided. See :ref:`rate limit override + // ` for more information. + Override limit = 4; } // .. attention:: diff --git a/envoy/config/route/v4alpha/route_components.proto b/envoy/config/route/v4alpha/route_components.proto index 8251d64c..1621fba5 100644 --- a/envoy/config/route/v4alpha/route_components.proto +++ b/envoy/config/route/v4alpha/route_components.proto @@ -1479,6 +1479,30 @@ message RateLimit { } } + message Override { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.route.v3.RateLimit.Override"; + + // Fetches the override from the dynamic metadata. + message DynamicMetadata { + option (udpa.annotations.versioning).previous_message_type = + "envoy.config.route.v3.RateLimit.Override.DynamicMetadata"; + + // Metadata struct that defines the key and path to retrieve the struct value. + // The value must be a struct containing an integer "requests_per_unit" property + // and a "unit" property with a value parseable to :ref:`RateLimitUnit + // enum ` + type.metadata.v3.MetadataKey metadata_key = 1 [(validate.rules).message = {required: true}]; + } + + oneof override_specifier { + option (validate.required) = true; + + // Limit override from dynamic metadata. + DynamicMetadata dynamic_metadata = 1; + } + } + // Refers to the stage set in the filter. The rate limit configuration only // applies to filters with the same stage number. The default stage number is // 0. @@ -1498,6 +1522,12 @@ message RateLimit { // configuration. See :ref:`composing actions // ` for additional documentation. repeated Action actions = 3 [(validate.rules).repeated = {min_items: 1}]; + + // An optional limit override to be appended to the descriptor produced by this + // rate limit configuration. If the override value is invalid or cannot be resolved + // from metadata, no override is provided. See :ref:`rate limit override + // ` for more information. + Override limit = 4; } // .. attention:: diff --git a/envoy/extensions/common/ratelimit/v3/BUILD b/envoy/extensions/common/ratelimit/v3/BUILD index ee90746a..256b1e65 100644 --- a/envoy/extensions/common/ratelimit/v3/BUILD +++ b/envoy/extensions/common/ratelimit/v3/BUILD @@ -7,6 +7,7 @@ licenses(["notice"]) # Apache 2 api_proto_package( deps = [ "//envoy/api/v2/ratelimit:pkg", + "//envoy/type/v3:pkg", "@com_github_cncf_udpa//udpa/annotations:pkg", ], ) diff --git a/envoy/extensions/common/ratelimit/v3/ratelimit.proto b/envoy/extensions/common/ratelimit/v3/ratelimit.proto index 187ae3f2..9255deb4 100644 --- a/envoy/extensions/common/ratelimit/v3/ratelimit.proto +++ b/envoy/extensions/common/ratelimit/v3/ratelimit.proto @@ -2,6 +2,8 @@ syntax = "proto3"; package envoy.extensions.common.ratelimit.v3; +import "envoy/type/v3/ratelimit_unit.proto"; + import "udpa/annotations/status.proto"; import "udpa/annotations/versioning.proto"; import "validate/validate.proto"; @@ -54,6 +56,10 @@ option (udpa.annotations.file_status).package_version_status = ACTIVE; // // The idea behind the API is that (1)/(2)/(3) and (4)/(5) can be sent in 1 request if desired. // This enables building complex application scenarios with a generic backend. +// +// Optionally the descriptor can contain a limit override under a "limit" key, that specifies +// the number of requests per unit to use instead of the number configured in the +// rate limiting service. message RateLimitDescriptor { option (udpa.annotations.versioning).previous_message_type = "envoy.api.v2.ratelimit.RateLimitDescriptor"; @@ -69,6 +75,20 @@ message RateLimitDescriptor { string value = 2 [(validate.rules).string = {min_bytes: 1}]; } + // Override rate limit to apply to this descriptor instead of the limit + // configured in the rate limit service. See :ref:`rate limit override + // ` for more information. + message RateLimitOverride { + // The number of requests per unit of time. + uint32 requests_per_unit = 1; + + // The unit of time. + type.v3.RateLimitUnit unit = 2 [(validate.rules).enum = {defined_only: true}]; + } + // Descriptor entries. repeated Entry entries = 1 [(validate.rules).repeated = {min_items: 1}]; + + // Optional rate limit override to supply to the ratelimit service. + RateLimitOverride limit = 2; } diff --git a/envoy/service/ratelimit/v3/rls.proto b/envoy/service/ratelimit/v3/rls.proto index 4aad42fc..06cb6a9e 100644 --- a/envoy/service/ratelimit/v3/rls.proto +++ b/envoy/service/ratelimit/v3/rls.proto @@ -69,6 +69,8 @@ message RateLimitResponse { option (udpa.annotations.versioning).previous_message_type = "envoy.service.ratelimit.v2.RateLimitResponse.RateLimit"; + // Identifies the unit of of time for rate limit. + // [#comment: replace by envoy/type/v3/ratelimit_unit.proto in v4] enum Unit { // The time unit is not known. UNKNOWN = 0; diff --git a/envoy/type/v3/ratelimit_unit.proto b/envoy/type/v3/ratelimit_unit.proto new file mode 100644 index 00000000..a3fb27ff --- /dev/null +++ b/envoy/type/v3/ratelimit_unit.proto @@ -0,0 +1,30 @@ +syntax = "proto3"; + +package envoy.type.v3; + +import "udpa/annotations/status.proto"; + +option java_package = "io.envoyproxy.envoy.type.v3"; +option java_outer_classname = "RatelimitUnitProto"; +option java_multiple_files = true; +option (udpa.annotations.file_status).package_version_status = ACTIVE; + +// [#protodoc-title: Ratelimit Time Unit] + +// Identifies the unit of of time for rate limit. +enum RateLimitUnit { + // The time unit is not known. + UNKNOWN = 0; + + // The time unit representing a second. + SECOND = 1; + + // The time unit representing a minute. + MINUTE = 2; + + // The time unit representing an hour. + HOUR = 3; + + // The time unit representing a day. + DAY = 4; +}