-
Notifications
You must be signed in to change notification settings - Fork 4.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support for multiple weighted clusters in routing (#361)
- Loading branch information
1 parent
cfeaab7
commit 2debf05
Showing
6 changed files
with
683 additions
and
28 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,3 +56,4 @@ response_headers_to_remove | |
rate_limits | ||
route_matching | ||
traffic_shifting | ||
weighted_routing |
120 changes: 120 additions & 0 deletions
120
docs/configuration/http_conn_man/route_config/weighted_routing.rst
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,120 @@ | ||
.. _config_http_conn_man_route_table_weighted_routing: | ||
|
||
Traffic splitting across multiple upstreams | ||
=========================================== | ||
|
||
Envoy's router can split traffic to a route in a virtual host across | ||
multiple upstream clusters. There are two common use cases. The first use | ||
case is version upgrades, where traffic to a route is shifted gradually | ||
from one cluster to another. The | ||
:ref:`traffic shifting <config_http_conn_man_route_table_traffic_shifting>` | ||
describes this scenario in more detail. | ||
|
||
The second use case, discussed in this section, is A/B testing or multivariate | ||
testing, where ``two or more versions`` of the same service are tested simultaneously. | ||
The traffic to the route has to be *split* between clusters running different versions | ||
of the same service. | ||
|
||
Consider a simple example ``service`` with three versions (v1, v2 and | ||
v3). Envoy provides two ways to split traffic evenly across the three | ||
versions (i.e., ``33%, 33%, 34%``): | ||
|
||
.. _config_http_conn_man_route_table_weighted_routing_percentages: | ||
|
||
(a) Weight-based cluster selection | ||
---------------------------------- | ||
|
||
The first option is to use a **single** :ref:`route <config_http_conn_man_route_table_route>` with | ||
:ref:`weighted_clusters <config_http_conn_man_route_table_route_weighted_clusters>`, | ||
where multiple upstream cluster targets are specified for a single route, | ||
along with weights that indicate the **percentage** of traffic to be sent | ||
to each upstream cluster. | ||
|
||
.. code-block:: json | ||
{ | ||
"route_config": { | ||
"virtual_hosts": [ | ||
{ | ||
"name": "service", | ||
"domains": ["*"], | ||
"routes": [ | ||
{ | ||
"prefix": "/", | ||
"weighted_clusters": { | ||
"runtime_key_prefix" : "routing.traffic_split.service", | ||
"clusters" : [ | ||
{ "name" : "service_v1", "weight" : 33 }, | ||
{ "name" : "service_v2", "weight" : 33 }, | ||
{ "name" : "service_v3", "weight" : 34 } | ||
] | ||
} | ||
} | ||
] | ||
} | ||
] | ||
} | ||
} | ||
The weights assigned to each cluster can be dynamically adjusted using the | ||
following runtime variables: ``routing.traffic_split.service.service_v1``, | ||
``routing.traffic_split.service.service_v2`` and | ||
``routing.traffic_split.service.service_v3``. | ||
|
||
.. _config_http_conn_man_route_table_weighted_routing_probabilities: | ||
|
||
(b) Probabilistic route selection | ||
--------------------------------- | ||
|
||
The second option is to use **multiple** :ref:`routes <config_http_conn_man_route_table_route>` | ||
with :ref:`runtimes <config_http_conn_man_route_table_route_runtime>` that specify the | ||
**probability** of selecting a route. | ||
Since Envoy matches routes with a :ref:`first match <config_http_conn_man_route_table_route_matching>` | ||
policy, the related routes (one for each upstream cluster) must be placed back-to-back, | ||
along with a runtime in all but the last route. | ||
|
||
.. code-block:: json | ||
{ | ||
"route_config": { | ||
"virtual_hosts": [ | ||
{ | ||
"name": "service", | ||
"domains": ["*"], | ||
"routes": [ | ||
{ | ||
"prefix": "/", | ||
"cluster": "service_v1", | ||
"runtime": { | ||
"key": "routing.traffic_split.service.service_v1", | ||
"default": 33 | ||
} | ||
}, | ||
{ | ||
"prefix": "/", | ||
"cluster": "service_v2", | ||
"runtime": { | ||
"key": "routing.traffic_split.service.service_v2", | ||
"default": 50 | ||
} | ||
}, | ||
{ | ||
"prefix": "/", | ||
"cluster": "service_v3", | ||
} | ||
] | ||
} | ||
] | ||
} | ||
} | ||
In the configuration above, | ||
|
||
1. ``routing.traffic_split.service.service_v1`` is set to ``33``, so that there is a | ||
*33\% probability* that the v1 route will be selected by Envoy. | ||
2. ``routing.traffic_split.service.service_v2`` is set to ``50``, so that if the v1 route | ||
is not selected, between v2 and v3, there is a *50\% probability* that the v2 route will | ||
be selected by Envoy. If v2 is not selected the traffic falls through to the v3 route. | ||
|
||
This distribution of probabilities ensures that the traffic will be split evenly across | ||
all three routes (i.e. ``33%, 33%, 34%``). |
Oops, something went wrong.