Support for multiple weighted clusters in routing#361
Support for multiple weighted clusters in routing#361mattklein123 merged 14 commits intoenvoyproxy:masterfrom
Conversation
mattklein123
left a comment
There was a problem hiding this comment.
re: runtime, I think it wouldn't be too hard to add (we could just do it inline and abort runtime processing if the values are wrong, but I think it's OK to ignore this for now. We can do it in a follow up if we need it.
source/common/router/config_impl.cc
Outdated
There was a problem hiding this comment.
There is no point in having this method (the base matches method) return a Route*. Just have it return bool like it used to (and change method name to something else so it's not an override).
source/common/router/config_impl.cc
Outdated
There was a problem hiding this comment.
please, fix: static const uint64_t max_weight
source/common/router/config_impl.cc
Outdated
There was a problem hiding this comment.
This should be unique_ptr. I just looked and I'm not sure why RouteEntryImplBasePtr is a shared_ptr currently. Switch that to unique_ptr also.
source/common/router/config_impl.cc
Outdated
source/common/router/config_impl.cc
Outdated
There was a problem hiding this comment.
move comment into header file or into function.
source/common/router/config_impl.h
Outdated
There was a problem hiding this comment.
unique_ptr, newline before this line
source/common/router/config_impl.h
Outdated
There was a problem hiding this comment.
nit: please use normal layout of organizing overrides under a comment of the class they override, with any non-override methods at the top.
source/common/router/config_impl.h
Outdated
There was a problem hiding this comment.
nit: please wrap comments at 100 col length.
There was a problem hiding this comment.
nit: still needs comment wrapping fix
source/common/router/config_impl.h
Outdated
There was a problem hiding this comment.
Should never happen, return nullptr.
source/common/router/config_impl.h
Outdated
There was a problem hiding this comment.
should never happen, return this.
c31b83f to
cb69f9d
Compare
|
added runtime support as well. |
| *(sometimes required, string)* If the route is not a redirect (*host_redirect* and/or | ||
| *path_redirect* is specified), *cluster* must be specified and indicates which upstream cluster | ||
| the request should be forwarded to. | ||
| *(sometimes required, string)* If the route is not a redirect (i.e., *host_redirect* and/or |
| priority_(ConfigUtility::parsePriority(route)) { | ||
|
|
||
| bool have_weighted_clusters = route.hasObject("weighted_clusters"); | ||
| bool have_cluster = !cluster_name_.empty() || have_weighted_clusters; |
mattklein123
left a comment
There was a problem hiding this comment.
overall looks good. small small comments/nits
| ----------------- | ||
|
|
||
| Compared to the ``cluster`` field that specifies a single upstream cluster as the target | ||
| of a request, the ``weighted_clusters`` allows for specification of multiple upstream clusters |
There was a problem hiding this comment.
"the weighted_clusters option..."
|
|
||
| weight | ||
| *(required, integer)* An integer between 0-100. When a request matches the route, | ||
| choice of an upstream cluster is determined by its weight. The sum of |
| weight | ||
| *(required, integer)* An integer between 0-100. When a request matches the route, | ||
| choice of an upstream cluster is determined by its weight. The sum of | ||
| weights across all entries in the ``clusters`` array should add up to 100. |
|
|
||
| .. _config_http_conn_man_route_table_weighted_routing_probabilities: | ||
|
|
||
| (b) Probabilistic route selection |
There was a problem hiding this comment.
This is somewhat of a duplication of https://lyft.github.io/envoy/docs/configuration/http_conn_man/route_config/traffic_shifting.html can we link and/or de-dup.
There was a problem hiding this comment.
So I considered that briefly. I couldn't link/reuse that document as is, because it was targeting a 2 cluster use case. Without a 3 cluster example, pointing to that document was sort of giving the incorrect impression that you can create multiple route blocks, where the value can be distributed just like weighted clusters (e.g., 33, 33, 34).
On the other hand, moving the three cluster example to traffic_shifting didn't make sense either, because the title of the page was "traffic shifting from one version to another". IOW,
The traffic shift describes a basic simple use case (moving from one version to another). Traffic splitting describes a more generic use case (using a 3 cluster example to differentiate weights vs probabilities. It is applicable to the 2 version use case as well).
If we go down the de-dup path, we could eliminate traffic shifting, with the assumption that the 3 cluster example for probability based splitting will be sufficient to construct a 2-cluster example as well. IOW, kill traffic shift, keep traffic split. Thoughts?
There was a problem hiding this comment.
I think I would kill traffic shifting in place of your new docs. @junr03 thoughts? You wrote the other doc.
There was a problem hiding this comment.
P.S., you might just add a brief sentence or something to your doc that mentions the 2 cluster case. Whatever you think is best is fine with me.
There was a problem hiding this comment.
yes, thats what I was thinking. if you and @junr03 have no objection to killing the traffic shifting doc, I was thinking of changing the weighted_routing to Traffic Splitting/Shifting, and add an example of two cluster case as well.
There was a problem hiding this comment.
It looks like that would be a bigger change. For the moment, i have linked out to the traffic shifting doc as @mattklein123 suggested
source/common/router/config_impl.cc
Outdated
|
|
||
| const Json::ObjectPtr weighted_clusters_json = route.getObject("weighted_clusters"); | ||
|
|
||
| if (!weighted_clusters_json->hasObject("clusters")) { |
There was a problem hiding this comment.
I would just delete this check, we will catch this with schema (makes code simpler).
source/common/router/config_impl.cc
Outdated
| for (const RouteEntryImplBasePtr& route : routes_) { | ||
| if (route->matches(headers, random_value)) { | ||
| return route.get(); | ||
| const Route* cEntry = route->matches(headers, random_value); |
There was a problem hiding this comment.
That would throw an error since route is the iteration variable in the for loop. I could rename it to something more sensible.
There was a problem hiding this comment.
sorry, just pick another name like "entry" or "route_entry"
source/common/router/config_impl.h
Outdated
There was a problem hiding this comment.
nit: still needs comment wrapping fix
source/common/router/config_impl.h
Outdated
| return loader_.snapshot().getInteger(runtime_key_, cluster_weight_); | ||
| } | ||
|
|
||
| static const uint64_t MAX_CLUSTER_WEIGHT; |
There was a problem hiding this comment.
nit: variable definitions go below method definitions
source/common/router/config_impl.h
Outdated
| const std::string runtime_key_; | ||
| Runtime::Loader& loader_; | ||
| const std::string cluster_name_; | ||
| uint64_t cluster_weight_; |
| const std::string cluster_name_; | ||
| uint64_t cluster_weight_; | ||
| }; | ||
| typedef std::unique_ptr<WeightedClusterEntry> WeightedClusterEntryPtr; |
There was a problem hiding this comment.
nit: newline before this line
There was a problem hiding this comment.
what's the convention for new lines?
There was a problem hiding this comment.
I don't have anything typed out (sorry), and clang-format doesn't check for this. You can look at the rest of the code base which in general is very consistent. I'm sorry that this is annoying but it's important to keep things consistent and you will pick it up pretty quickly.
|
addressed all except the traffic shifting/splitting issue. Waiting on feedback from @junr03 . |
| .. _config_http_conn_man_route_table_route_cluster: | ||
|
|
||
| cluster | ||
| *(sometimes required, string)* If the route is not a redirect (i.e., *host_redirect* and/or |
| EXPECT_EQ(nullptr, config.route(headers, 0)->redirectEntry()); | ||
| EXPECT_EQ("www2", config.route(headers, 0)->routeEntry()->clusterName()); | ||
| } | ||
| { |
| } | ||
| } | ||
|
|
||
| TEST(RouteMatcherTest, WeightedClusters) { |
There was a problem hiding this comment.
nit: Please add a test where random value is greater than 100.
|
@rshriram after reading your doc it is obvious to me how you could do traffic shifting with the same mechanism, so I agree that having both docs is somewhat duplication. However, I think that it is better to have a traffic shifting example to make the use case explicit for users. I think it would be best to merge the two docs, eliminating duplicate info from the traffic shifting doc as needed. |
mattklein123
left a comment
There was a problem hiding this comment.
looks great. thank you for all the fixes/changes.
|
@junr03 I will send a separate PR to merge the two docs. |
|
great! |
* Removed pending requests management * Exposed ConfigLoadingStatus * Added description of the config loading status
Automatic merge from submit-queue. [DO NOT MERGE] Auto PR to update dependencies of mixerclient This PR will be merged automatically once checks are successful. ```release-note none ```
Signed-off-by: Kuat Yessenov <kuat@google.com>
**Commit Message** This adds timeouts field on AIServiceBackend to allow the configuration of timeouts per backend. **Related Issues/PRs (if applicable)** Fixes #361 --------- Signed-off-by: Loong <long0dai@foxmail.com>
[apologies for the delayed turn around for this feature].
This PR provides an intuitive way of specifying cluster weights, when a particular route is backed by two or more clusters. Instead of using the existing Runtime style probability specification, users can group related clusters under a single weighted_clusters block with % weights assigned to each cluster.
Please refer to #247 for more details.
The current PR is missing documentation. Will add that in a day or so. TLDR:
In the routing config, you can have either the
clusterkey or theweighted_clusterskey.The
weighted_clustersis of the following format:where N is an integer from 0 to 100. It determines the proportion of request traffic to be sent to the target cluster. The sum of all weights in the weighted cluster should be equal to 100.
On runtime support for weighted clusters: If we wish to validate the weights provided by the user (as we do it currently), it is not exactly clear how the weights would be validated (i.e. sum of weights == 100) if runtime support were to be enabled for a weighted cluster. My current inclination is to skip runtime support altogether for weighted_clusters. With the addition of RDS, a user can combine weighted cluster and RDS to dynamically change weights. It may not occur instantaneously (as it depends on the RDS poll interval).
Fixes #247
@mattklein123 @ccaraman
p.s.: For reviewing this PR, please do not look at the individual commits. Instead, I suggest looking at config_impl.h|cc as one change set and then config_impl_test.cc as another change set.