mirror of https://github.com/istio/istio.io.git
216 lines
7.5 KiB
Markdown
216 lines
7.5 KiB
Markdown
---
|
|
title: Enabling Rate Limits
|
|
overview: This task shows you how to use Istio to dynamically limit the traffic to a service.
|
|
|
|
order: 80
|
|
|
|
layout: docs
|
|
type: markdown
|
|
---
|
|
{% include home.html %}
|
|
|
|
This task shows you how to use Istio to dynamically limit the traffic to a service.
|
|
|
|
## Before you begin
|
|
|
|
* Setup Istio by following the instructions in the
|
|
[Installation guide](./installing-istio.html).
|
|
|
|
* Deploy the [BookInfo]({{home}}/docs/samples/bookinfo.html) sample application.
|
|
|
|
* Initialize the application version routing to direct `reviews` service requests from
|
|
test user "jason" to version v2 and requests from any other user to v3.
|
|
|
|
```bash
|
|
istioctl create -f samples/apps/bookinfo/route-rule-reviews-test-v2.yaml
|
|
istioctl create -f samples/apps/bookinfo/route-rule-reviews-v3.yaml
|
|
```
|
|
|
|
> Note: if you have conflicting rule that you set in previous tasks,
|
|
use `istioctl replace` instead of `istioctl create`.
|
|
|
|
## Rate limits
|
|
|
|
Istio enables users to rate limit traffic to a service.
|
|
|
|
Consider `ratings` as an external paid service like Rotten Tomatoes® with `1qps` free quota.
|
|
Using Istio we can ensure that `1qps` is not breached.
|
|
|
|
1. Point your browser at the BookInfo `productpage` (http://$GATEWAY_URL/productpage).
|
|
|
|
If you log in as user "jason", you should see black ratings stars with each review,
|
|
indicating that the `ratings` service is being called by the "v2" version of the `reviews` service.
|
|
|
|
If you log in as any other user (or logout) you should see red ratings stars with each review,
|
|
indicating that the `ratings` service is being called by the "v3" version of the `reviews` service.
|
|
|
|
1. Configure mixer with the rate limit.
|
|
|
|
Save this as ratelimit.yaml:
|
|
|
|
```yaml
|
|
rules:
|
|
- aspects:
|
|
- kind: quotas
|
|
params:
|
|
quotas:
|
|
- descriptorName: RequestCount
|
|
maxAmount: 1
|
|
expiration: 1s
|
|
```
|
|
|
|
and then run the following command:
|
|
|
|
```bash
|
|
istioctl mixer rule create global ratings.default.svc.cluster.local -f ratelimit.yaml
|
|
```
|
|
|
|
`istioctl` sets configuration for `subject=ratings.default.svc.cluster.local`
|
|
|
|
1. Generate load on the `productpage` with the following command:
|
|
|
|
```bash
|
|
while true; do curl -s -o /dev/null http://$GATEWAY_URL/productpage; done
|
|
```
|
|
|
|
1. Refresh the `productpage` in your browser.
|
|
|
|
While the load generator is running (i.e., generating more than 1 req/s), the traffic generated by
|
|
your browser will be rate limited.
|
|
Notice that if you log in as user "jason" or any other user, the `reviews` service is unable to
|
|
access the `ratings` service, so you stop seeing stars, red or black.
|
|
|
|
## Conditional rate limits
|
|
|
|
In the previous example we applied a rate limit to the `ratings` service without regard
|
|
to any other attributes. It is possible to conditionally apply rate limits based on
|
|
attributes like the source of the traffic.
|
|
|
|
The following configuration applies a `1qps` rate limit only to version `v3` of `reviews`.
|
|
|
|
1. Configure mixer with the conditional rate limit.
|
|
|
|
Save this as ratelimit-conditional.yaml:
|
|
|
|
```yaml
|
|
rules:
|
|
- selector: source.labels["app"]=="reviews" && source.labels["version"] == "v3"
|
|
aspects:
|
|
- kind: quotas
|
|
params:
|
|
quotas:
|
|
- descriptorName: RequestCount
|
|
maxAmount: 1
|
|
expiration: 1s
|
|
```
|
|
|
|
and then run the following command:
|
|
|
|
```bash
|
|
istioctl mixer rule create global ratings.default.svc.cluster.local -f ratelimit-conditional.yaml
|
|
```
|
|
|
|
Notice the rule is the same as the previous example, only this one uses a `selector` to
|
|
apply the ratelimit only for requests from `reviews:v3`.
|
|
|
|
1. Generate load on the `productpage` with the following command:
|
|
|
|
```bash
|
|
while true; do curl -s -o /dev/null http://$GATEWAY_URL/productpage; done
|
|
```
|
|
|
|
1. Refresh the `productpage` in your browser.
|
|
|
|
As in the previous example, while the load
|
|
generator is running (i.e., generating more than 1 req/s), the traffic generated by
|
|
your browser will be rate limited, but this time only if the request is from `reviews:v3`.
|
|
Notice that this time if you log in as user "jason" (the `reviews:v2` user) you will continue to see
|
|
the black ratings stars. Only the other users will stop seeing
|
|
the red ratings stars while the load generator is running.
|
|
|
|
## Understanding rate limits
|
|
|
|
In the preceding examples we saw how Mixer applies rate limits to requests that match certain conditions.
|
|
|
|
Every distinct rate limit configuration represents a counter. If the number
|
|
of requests in the last `expiration` duration exceed `maxAmount`, Mixer returns a `RESOURCE_EXHAUSTED`
|
|
message to the proxy. The proxy in turn returns status `HTTP 429` to the caller.
|
|
|
|
Multiple rate limits may apply to the same request.
|
|
|
|
Mixer `MemQuota` adapter uses a sliding window of sub second resolution to enforce rate limits.
|
|
|
|
Consider the following example
|
|
|
|
```yaml
|
|
descriptorName: RequestCount
|
|
maxAmount: 5000
|
|
expiration: 5s
|
|
labels:
|
|
label1: target.service
|
|
```
|
|
This defines a set of counters with a limit of `5000` per every `5 seconds`.
|
|
Individual counters within the set are identified by unique keys. A key is formed on the request path by using all parameters
|
|
of the configuration. Here we introduce the notion of labels that enable creation of more granular counter keys.
|
|
When a request arrives at Mixer with `target.service=ratings` it forms the following counter key.
|
|
|
|
```$aspect_id;RequestCount;maxAmount=5000;expiration=5s;label1=ratings ```
|
|
|
|
Using `target.service` in the counter key enables independent rate limits for every service.
|
|
In absence of `target.service` as part of the key, the same counter location is used by all services resulting in
|
|
combined rate limit of `5000` requests per `5 seconds`
|
|
|
|
Mixer supports an arbitrary number of labels by defining `QuotaDescriptors`.
|
|
```yaml
|
|
name: RequestCount
|
|
rate_limit: true
|
|
labels:
|
|
label1: 1 # STRING
|
|
```
|
|
Here we define `RequestCount` quota descriptor that takes 1 string label. We recommend using meaningful label names
|
|
even though label names are arbitrary.
|
|
|
|
```yaml
|
|
name: RequestCount_byService_byUser
|
|
rate_limit: true
|
|
labels:
|
|
service: 1 # STRING
|
|
user: 1 # STRING
|
|
```
|
|
Mixer expects `user,service` labels when the `RequestCount_byService_byUser` descriptor is used and produces
|
|
the following config validation error if any labels are missing.
|
|
```bash
|
|
* quotas: aspect validation failed: 1 error occurred:
|
|
* quotas[RequestCount_byService_byUser].labels: wrong dimensions: descriptor expects 2 labels, found 0 labels
|
|
```
|
|
|
|
## Cleanup
|
|
|
|
* Remove the mixer configuration rule:
|
|
|
|
```bash
|
|
istioctl mixer rule create global ratings.default.svc.cluster.local -f samples/apps/bookinfo/mixer-rule-empty-rule.yaml
|
|
```
|
|
|
|
> Note: removing a rule by setting an empty rule list is a temporary workaround because `istioctl delete` does not
|
|
yet support mixer rules.
|
|
|
|
* Remove the application routing rules:
|
|
|
|
```
|
|
istioctl delete -f samples/apps/bookinfo/route-rule-reviews-test-v2.yaml
|
|
istioctl delete -f samples/apps/bookinfo/route-rule-reviews-v3.yaml
|
|
```
|
|
|
|
## What's next
|
|
|
|
* Learn more about [Mixer]({{home}}/docs/concepts/policy-and-control/mixer.html) and [Mixer Config]({{home}}/docs/concepts/policy-and-control/mixer-config.html).
|
|
|
|
* Discover the full [Attribute Vocabulary]({{home}}/docs/reference/config/mixer/attribute-vocabulary.html).
|
|
|
|
* Read the reference guide to [Writing Config]({{home}}/docs/reference/writing-config.html).
|
|
|
|
* If you are not planning to explore any follow-on tasks, refer to the
|
|
[BookInfo cleanup]({{home}}/docs/samples/bookinfo.html#cleanup) instructions
|
|
to shutdown the application and cleanup the associated rules.
|