You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
250 lines
13 KiB
250 lines
13 KiB
syntax = "proto3"; |
|
|
|
package envoy.service.rate_limit_quota.v3; |
|
|
|
import "envoy/type/v3/ratelimit_strategy.proto"; |
|
|
|
import "google/protobuf/duration.proto"; |
|
|
|
import "xds/annotations/v3/status.proto"; |
|
|
|
import "udpa/annotations/status.proto"; |
|
import "validate/validate.proto"; |
|
|
|
option java_package = "io.envoyproxy.envoy.service.rate_limit_quota.v3"; |
|
option java_outer_classname = "RlqsProto"; |
|
option java_multiple_files = true; |
|
option go_package = "github.com/envoyproxy/go-control-plane/envoy/service/rate_limit_quota/v3;rate_limit_quotav3"; |
|
option (udpa.annotations.file_status).package_version_status = ACTIVE; |
|
option (xds.annotations.v3.file_status).work_in_progress = true; |
|
|
|
// [#protodoc-title: Rate Limit Quota Service (RLQS)] |
|
|
|
// The Rate Limit Quota Service (RLQS) is a Envoy global rate limiting service that allows to |
|
// delegate rate limit decisions to a remote service. The service will aggregate the usage reports |
|
// from multiple data plane instances, and distribute Rate Limit Assignments to each instance |
|
// based on its business logic. The logic is outside of the scope of the protocol API. |
|
// |
|
// The protocol is designed as a streaming-first API. It utilizes watch-like subscription model. |
|
// The data plane groups requests into Quota Buckets as directed by the filter config, |
|
// and periodically reports them to the RLQS server along with the Bucket identifier, :ref:`BucketId |
|
// <envoy_v3_api_msg_service.rate_limit_quota.v3.BucketId>`. Once RLQS server has collected enough |
|
// reports to make a decision, it'll send back the assignment with the rate limiting instructions. |
|
// |
|
// The first report sent by the data plane is interpreted by the RLQS server as a "watch" request, |
|
// indicating that the data plane instance is interested in receiving further updates for the |
|
// ``BucketId``. From then on, RLQS server may push assignments to this instance at will, even if |
|
// the instance is not sending usage reports. It's the responsibility of the RLQS server |
|
// to determine when the data plane instance didn't send ``BucketId`` reports for too long, |
|
// and to respond with the :ref:`AbandonAction |
|
// <envoy_v3_api_msg_service.rate_limit_quota.v3.RateLimitQuotaResponse.BucketAction.AbandonAction>`, |
|
// indicating that the server has now stopped sending quota assignments for the ``BucketId`` bucket, |
|
// and the data plane instance should :ref:`abandon |
|
// <envoy_v3_api_field_service.rate_limit_quota.v3.RateLimitQuotaResponse.BucketAction.abandon_action>` |
|
// it. |
|
// |
|
// Refer to Rate Limit Quota :ref:`configuration overview <config_http_filters_rate_limit_quota>` |
|
// for further details. |
|
|
|
// Defines the Rate Limit Quota Service (RLQS). |
|
service RateLimitQuotaService { |
|
// Main communication channel: the data plane sends usage reports to the RLQS server, |
|
// and the server asynchronously responding with the assignments. |
|
rpc StreamRateLimitQuotas(stream RateLimitQuotaUsageReports) |
|
returns (stream RateLimitQuotaResponse) { |
|
} |
|
} |
|
|
|
message RateLimitQuotaUsageReports { |
|
// The usage report for a bucket. |
|
// |
|
// .. note:: |
|
// Note that the first report sent for a ``BucketId`` indicates to the RLQS server that |
|
// the RLQS client is subscribing for the future assignments for this ``BucketId``. |
|
message BucketQuotaUsage { |
|
// ``BucketId`` for which request quota usage is reported. |
|
BucketId bucket_id = 1 [(validate.rules).message = {required: true}]; |
|
|
|
// Time elapsed since the last report. |
|
google.protobuf.Duration time_elapsed = 2 [(validate.rules).duration = { |
|
required: true |
|
gt {} |
|
}]; |
|
|
|
// Requests the data plane has allowed through. |
|
uint64 num_requests_allowed = 3; |
|
|
|
// Requests throttled. |
|
uint64 num_requests_denied = 4; |
|
} |
|
|
|
// All quota requests must specify the domain. This enables sharing the quota |
|
// server between different applications without fear of overlap. |
|
// E.g., "envoy". |
|
// |
|
// Should only be provided in the first report, all subsequent messages on the same |
|
// stream are considered to be in the same domain. In case the domain needs to be |
|
// changes, close the stream, and reopen a new one with the different domain. |
|
string domain = 1 [(validate.rules).string = {min_len: 1}]; |
|
|
|
// A list of quota usage reports. The list is processed by the RLQS server in the same order |
|
// it's provided by the client. |
|
repeated BucketQuotaUsage bucket_quota_usages = 2 [(validate.rules).repeated = {min_items: 1}]; |
|
} |
|
|
|
message RateLimitQuotaResponse { |
|
// Commands the data plane to apply one of the actions to the bucket with the |
|
// :ref:`bucket_id <envoy_v3_api_field_service.rate_limit_quota.v3.RateLimitQuotaResponse.BucketAction.bucket_id>`. |
|
message BucketAction { |
|
// Quota assignment for the bucket. Configures the rate limiting strategy and the duration |
|
// for the given :ref:`bucket_id |
|
// <envoy_v3_api_field_service.rate_limit_quota.v3.RateLimitQuotaResponse.BucketAction.bucket_id>`. |
|
// |
|
// **Applying the first assignment to the bucket** |
|
// |
|
// Once the data plane receives the ``QuotaAssignmentAction``, it must send the current usage |
|
// report for the bucket, and start rate limiting requests matched into the bucket |
|
// using the strategy configured in the :ref:`rate_limit_strategy |
|
// <envoy_v3_api_field_service.rate_limit_quota.v3.RateLimitQuotaResponse.BucketAction.QuotaAssignmentAction.rate_limit_strategy>` |
|
// field. The assignment becomes bucket's ``active`` assignment. |
|
// |
|
// **Expiring the assignment** |
|
// |
|
// The duration of the assignment defined in the :ref:`assignment_time_to_live |
|
// <envoy_v3_api_field_service.rate_limit_quota.v3.RateLimitQuotaResponse.BucketAction.QuotaAssignmentAction.assignment_time_to_live>` |
|
// field. When the duration runs off, the assignment is ``expired``, and no longer ``active``. |
|
// The data plane should stop applying the rate limiting strategy to the bucket, and transition |
|
// the bucket to the "expired assignment" state. This activates the behavior configured in the |
|
// :ref:`expired_assignment_behavior <envoy_v3_api_field_extensions.filters.http.rate_limit_quota.v3.RateLimitQuotaBucketSettings.expired_assignment_behavior>` |
|
// field. |
|
// |
|
// **Replacing the assignment** |
|
// |
|
// * If the rate limiting strategy is different from bucket's ``active`` assignment, or |
|
// the current bucket assignment is ``expired``, the data plane must immediately |
|
// end the current assignment, report the bucket usage, and apply the new assignment. |
|
// The new assignment becomes bucket's ``active`` assignment. |
|
// * If the rate limiting strategy is the same as the bucket's ``active`` (not ``expired``) |
|
// assignment, the data plane should extend the duration of the ``active`` assignment |
|
// for the duration of the new assignment provided in the :ref:`assignment_time_to_live |
|
// <envoy_v3_api_field_service.rate_limit_quota.v3.RateLimitQuotaResponse.BucketAction.QuotaAssignmentAction.assignment_time_to_live>` |
|
// field. The ``active`` assignment is considered unchanged. |
|
message QuotaAssignmentAction { |
|
// A duration after which the assignment is be considered ``expired``. The process of the |
|
// expiration is described :ref:`above |
|
// <envoy_v3_api_msg_service.rate_limit_quota.v3.RateLimitQuotaResponse.BucketAction.QuotaAssignmentAction>`. |
|
// |
|
// * If unset, the assignment has no expiration date. |
|
// * If set to ``0``, the assignment expires immediately, forcing the client into the |
|
// :ref:`"expired assignment" |
|
// <envoy_v3_api_field_extensions.filters.http.rate_limit_quota.v3.RateLimitQuotaBucketSettings.ExpiredAssignmentBehavior.expired_assignment_behavior_timeout>` |
|
// state. This may be used by the RLQS server in cases when it needs clients to proactively |
|
// fall back to the pre-configured :ref:`ExpiredAssignmentBehavior |
|
// <envoy_v3_api_msg_extensions.filters.http.rate_limit_quota.v3.RateLimitQuotaBucketSettings.ExpiredAssignmentBehavior>`, |
|
// f.e. before the server going into restart. |
|
// |
|
// .. attention:: |
|
// Note that :ref:`expiring |
|
// <envoy_v3_api_msg_service.rate_limit_quota.v3.RateLimitQuotaResponse.BucketAction.QuotaAssignmentAction>` |
|
// the assignment is not the same as :ref:`abandoning |
|
// <envoy_v3_api_msg_service.rate_limit_quota.v3.RateLimitQuotaResponse.BucketAction.AbandonAction>` |
|
// the assignment. While expiring the assignment just transitions the bucket to |
|
// the "expired assignment" state; abandoning the assignment completely erases |
|
// the bucket from the data plane memory, and stops the usage reports. |
|
google.protobuf.Duration assignment_time_to_live = 2 [(validate.rules).duration = {gte {}}]; |
|
|
|
// Configures the local rate limiter for the request matched to the bucket. |
|
// If not set, allow all requests. |
|
type.v3.RateLimitStrategy rate_limit_strategy = 3; |
|
} |
|
|
|
// Abandon action for the bucket. Indicates that the RLQS server will no longer be |
|
// sending updates for the given :ref:`bucket_id |
|
// <envoy_v3_api_field_service.rate_limit_quota.v3.RateLimitQuotaResponse.BucketAction.bucket_id>`. |
|
// |
|
// If no requests are reported for a bucket, after some time the server considers the bucket |
|
// inactive. The server stops tracking the bucket, and instructs the the data plane to abandon |
|
// the bucket via this message. |
|
// |
|
// **Abandoning the assignment** |
|
// |
|
// The data plane is to erase the bucket (including its usage data) from the memory. |
|
// It should stop tracking the bucket, and stop reporting its usage. This effectively resets |
|
// the data plane to the state prior to matching the first request into the bucket. |
|
// |
|
// **Restarting the subscription** |
|
// |
|
// If a new request is matched into a bucket previously abandoned, the data plane must behave |
|
// as if it has never tracked the bucket, and it's the first request matched into it: |
|
// |
|
// 1. The process of :ref:`subscription and reporting |
|
// <envoy_v3_api_field_extensions.filters.http.rate_limit_quota.v3.RateLimitQuotaBucketSettings.reporting_interval>` |
|
// starts from the beginning. |
|
// |
|
// 2. The bucket transitions to the :ref:`"no assignment" |
|
// <envoy_v3_api_field_extensions.filters.http.rate_limit_quota.v3.RateLimitQuotaBucketSettings.no_assignment_behavior>` |
|
// state. |
|
// |
|
// 3. Once the new assignment is received, it's applied per |
|
// "Applying the first assignment to the bucket" section of the :ref:`QuotaAssignmentAction |
|
// <envoy_v3_api_msg_service.rate_limit_quota.v3.RateLimitQuotaResponse.BucketAction.QuotaAssignmentAction>`. |
|
message AbandonAction { |
|
} |
|
|
|
// ``BucketId`` for which request the action is applied. |
|
BucketId bucket_id = 1 [(validate.rules).message = {required: true}]; |
|
|
|
oneof bucket_action { |
|
option (validate.required) = true; |
|
|
|
// Apply the quota assignment to the bucket. |
|
// |
|
// Commands the data plane to apply a rate limiting strategy to the bucket. |
|
// The process of applying and expiring the rate limiting strategy is detailed in the |
|
// :ref:`QuotaAssignmentAction |
|
// <envoy_v3_api_msg_service.rate_limit_quota.v3.RateLimitQuotaResponse.BucketAction.QuotaAssignmentAction>` |
|
// message. |
|
QuotaAssignmentAction quota_assignment_action = 2; |
|
|
|
// Abandon the bucket. |
|
// |
|
// Commands the data plane to abandon the bucket. |
|
// The process of abandoning the bucket is described in the :ref:`AbandonAction |
|
// <envoy_v3_api_msg_service.rate_limit_quota.v3.RateLimitQuotaResponse.BucketAction.AbandonAction>` |
|
// message. |
|
AbandonAction abandon_action = 3; |
|
} |
|
} |
|
|
|
// An ordered list of actions to be applied to the buckets. The actions are applied in the |
|
// given order, from top to bottom. |
|
repeated BucketAction bucket_action = 1 [(validate.rules).repeated = {min_items: 1}]; |
|
} |
|
|
|
// The identifier for the bucket. Used to match the bucket between the control plane (RLQS server), |
|
// and the data plane (RLQS client), f.e.: |
|
// |
|
// * the data plane sends a usage report for requests matched into the bucket with ``BucketId`` |
|
// to the control plane |
|
// * the control plane sends an assignment for the bucket with ``BucketId`` to the data plane |
|
// Bucket ID. |
|
// |
|
// Example: |
|
// |
|
// .. validated-code-block:: yaml |
|
// :type-name: envoy.service.rate_limit_quota.v3.BucketId |
|
// |
|
// bucket: |
|
// name: my_bucket |
|
// env: staging |
|
// |
|
// .. note:: |
|
// The order of ``BucketId`` keys do not matter. Buckets ``{ a: 'A', b: 'B' }`` and |
|
// ``{ b: 'B', a: 'A' }`` are identical. |
|
message BucketId { |
|
map<string, string> bucket = 1 [(validate.rules).map = { |
|
min_pairs: 1 |
|
keys {string {min_len: 1}} |
|
values {string {min_len: 1}} |
|
}]; |
|
}
|
|
|