Skip to content

upstream: Fallback policy per selector support#7087

Merged
zuercher merged 20 commits intoenvoyproxy:masterfrom
nezdolik:subset-lb-opt
Jun 14, 2019
Merged

upstream: Fallback policy per selector support#7087
zuercher merged 20 commits intoenvoyproxy:masterfrom
nezdolik:subset-lb-opt

Conversation

@nezdolik
Copy link
Copy Markdown
Member

@nezdolik nezdolik commented May 28, 2019

Signed-off-by: Kateryna Nezdolii nezdolik@spotify.com

Duplicate of #6124 but with completed development.

Description: This code change allows to redefine fallback policy per specific subset selector. Because of how existing LbSubsetMap trie data structure is organised (mapping subset key to values), is not possible to do lookups for fallback policy only based on subset keys (had to introduce additional trie that maps subset keys to keys and has fallback policy on leaf level). Additional LbSubsetSelectorFallbackPolicy enum required to correctly identify the case when fallback policy is not set for given selector (otherwise it would always default to NO_FALLBACK, breaking backwards compatibility, if field is not set we should use top level fallback policy instead).

Risk Level: Medium
Testing: Done
Docs Changes: Updated related docs
Release Notes:
Fixes #5130

@htuch
Copy link
Copy Markdown
Member

htuch commented May 28, 2019

Please merge master to pick up #7090

@nezdolik nezdolik force-pushed the subset-lb-opt branch 2 times, most recently from 29d9cde to 5d33bfe Compare May 28, 2019 23:19
Comment thread include/envoy/upstream/load_balancer_type.h Outdated
@yanavlasov
Copy link
Copy Markdown
Contributor

yanavlasov commented May 29, 2019

Please add unit tests for the new functionality in the subset_lb_test.cc.
EDIT: sorry I see you have added it. Github decided it was too large and not rendered it.

Comment thread source/common/upstream/subset_lb.cc Outdated
@dio
Copy link
Copy Markdown
Member

dio commented May 29, 2019

@nezdolik seems like you need to fix DCO. Please follow this: https://github.com/envoyproxy/envoy/blob/master/CONTRIBUTING.md#fixing-dco

To avoid missing DCO in a pushed commit in the future seems like enabling the commit hook (./support/bootstrap) is not a bad idea https://github.com/envoyproxy/envoy/blob/master/CONTRIBUTING.md#dco-sign-your-work (it also helps to check the format)

Signed-off-by: Kateryna Nezdolii <nezdolik@spotify.com>
Kateryna Nezdolii added 3 commits May 29, 2019 10:52
Signed-off-by: Kateryna Nezdolii <nezdolik@spotify.com>
Signed-off-by: Kateryna Nezdolii <nezdolik@spotify.com>
Signed-off-by: Kateryna Nezdolii <nezdolik@spotify.com>
@yanavlasov
Copy link
Copy Markdown
Contributor

Please add user documentation for the new feature here https://github.com/envoyproxy/envoy/blob/master/docs/root/intro/arch_overview/load_balancing/subsets.rst

Comment thread include/envoy/upstream/load_balancer_type.h Outdated
}

void SubsetLoadBalancer::initSubsetSelectorMap() {
selectors_ = std::make_shared<SubsetSelectorMap>();
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since selectors_ is always initialized, I suggest moving its initialization to the constructor initializer list or better yet initialize it right in the header at the point of definition.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yanavlasov cannot init selectors_ in the header, as it depends on field subset_selectors_ being initialised in constructor. Moved out this initialisation into separate method, as constructor body is already big and it could be hard to read. What do you think?

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was suggesting to move just the first line where the pointer is initialized to point to an empty SubsetSelectorMap object to the header. However the way you have is fine as well.

Comment thread source/common/upstream/subset_lb.h Outdated
typedef std::unordered_map<HashedValue, LbSubsetEntryPtr> ValueSubsetMap;
typedef std::unordered_map<std::string, ValueSubsetMap> LbSubsetMap;

struct SubsetSelectorMap {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it is fine as it is. However you could likely simplify this. The subset fallback policy is fully identified by the set of selector keys for this subset. You can concatenate the sorted selector keys into one string and use it as a key for finding the fallback policy. In this way you do not need to build a trie and can just use std::unordered_set<std::string, envoy::api::v2::Cluster::LbSubsetConfig::LbSubsetSelectorFallbackPolicy>

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@yanavlasov agree that that way code would be simplified. Was thinking about tradeoff though, if to switch to plain map, on each lookupHosts call LB will have to perform concatenation of keys from match criteria to look it up in map. While first approach brings code complexity but is kind of precomputing things on LB object creation so that when lookupHosts called we just iterate over each match criteria key and look it up recursively in a trie. If it's not a big deal of match criteria keys concatenation (from memory usage perspective), then having plain map seems more beneficial.

Comment thread source/common/upstream/subset_lb.cc Outdated
Comment thread source/common/upstream/subset_lb.cc Outdated
Comment thread source/common/upstream/subset_lb.h Outdated
Comment thread test/common/upstream/subset_lb_test.cc Outdated
Kateryna Nezdolii added 2 commits May 31, 2019 18:09
Signed-off-by: Kateryna Nezdolii <nezdolik@spotify.com>
Signed-off-by: Kateryna Nezdolii <nezdolik@spotify.com>
@nezdolik nezdolik requested a review from htuch as a code owner May 31, 2019 16:09
@nezdolik
Copy link
Copy Markdown
Member Author

@yanavlasov addressed some of review comments (added testing for compound selector, switched to struct for SubsetSelector type, removed optional in struct), all others are in progress

Copy link
Copy Markdown
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

API level comments.
/wait

Comment thread api/envoy/api/v2/cds.proto Outdated
Comment thread api/envoy/api/v2/cds.proto Outdated
Signed-off-by: Kateryna Nezdolii <nezdolik@spotify.com>
@htuch htuch requested a review from zuercher June 6, 2019 04:25
Signed-off-by: Kateryna Nezdolii <nezdolik@spotify.com>
@nezdolik
Copy link
Copy Markdown
Member Author

nezdolik commented Jun 6, 2019

/retest

@repokitteh-read-only
Copy link
Copy Markdown

🔨 rebuilding ci/circleci: coverage (failed build)

🐱

Caused by: a #7087 (comment) was created by @nezdolik.

see: more, trace.

@rgs1
Copy link
Copy Markdown
Member

rgs1 commented Jun 6, 2019

@nezdolik should panic mode also be configurable per selector?

Copy link
Copy Markdown
Member

@zuercher zuercher left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks! I had a question about how the map of subset selectors/fallback policies is constructed, but otherwise I think it looks pretty good.

Comment thread source/common/upstream/subset_lb.cc Outdated
Comment thread source/common/upstream/subset_lb.cc Outdated
Comment thread source/common/upstream/subset_lb.cc Outdated
Comment thread source/common/upstream/subset_lb.h Outdated
Comment thread include/envoy/upstream/load_balancer_type.h
Comment thread test/common/upstream/subset_lb_test.cc Outdated
Comment thread api/envoy/api/v2/cds.proto
const auto& selector_keys = subset_selector->selector_keys_;
uint32_t pos = 0;
selectors = selectors_;
for (const auto& key : selector_keys) {
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What do you think about skipping this loop if subset_selector->fallback_policy_ is undefined? As it stands, the default behavior will be to build up this data structure with all the subsets even if no subset has a custom fallback policy configured. If you skip adding the subsets with no custom fallback, then SubsetSelectorMap.fallback_policy_ doesn't need to be optional and you can get rid of that complicated ternary below.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

agree, thanks for pointing out

Kateryna Nezdolii added 2 commits June 11, 2019 15:52
Signed-off-by: Kateryna Nezdolii <nezdolik@spotify.com>
Signed-off-by: Kateryna Nezdolii <nezdolik@spotify.com>
@nezdolik
Copy link
Copy Markdown
Member Author

nezdolik commented Jun 11, 2019

@rgs1 possibly yes, with this change in case there is override per selector and no hosts are found, nullptr is returned even if there is panic mode enabled on top level config.

Signed-off-by: Kateryna Nezdolii <nezdolik@spotify.com>
zuercher
zuercher previously approved these changes Jun 11, 2019
HostPredicate predicate = [](const Host&) -> bool { return true; };
selector_fallback_subset_any_ = std::make_unique<LbSubsetEntry>();
selector_fallback_subset_any_->priority_subset_.reset(
new PrioritySubsetImpl(*this, predicate, locality_weight_aware_, scale_locality_weight_));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: use make_shared() for consistency?

default_subset_metadata_, std::placeholders::_1);
selector_fallback_subset_default_ = std::make_unique<LbSubsetEntry>();
selector_fallback_subset_default_->priority_subset_.reset(
new PrioritySubsetImpl(*this, predicate, locality_weight_aware_, scale_locality_weight_));
Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ditto

rgs1 pushed a commit to rgs1/envoy that referenced this pull request Jun 11, 2019
While reading envoyproxy#7087, I noticed two things about subset_lb.{cc,h}:

* a few shared_ptrs are assigned via make_unique, which works
  but is wasteful [extra allocation]
* reset(new ...) is used, which is unsafe & not consistent with
  the rest of the file

Signed-off-by: Raul Gutierrez Segales <rgs@pinterest.com>
mattklein123 pushed a commit that referenced this pull request Jun 12, 2019
While reading #7087, I noticed two things about subset_lb.{cc,h}:

* a few shared_ptrs are assigned via make_unique, which works
  but is wasteful [extra allocation]
* reset(new ...) is used, which is unsafe & not consistent with
  the rest of the file

Signed-off-by: Raul Gutierrez Segales <rgs@pinterest.com>
htuch
htuch previously approved these changes Jun 13, 2019
Copy link
Copy Markdown
Member

@htuch htuch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved from API and general Envoy style perspective, will defer to @zuercher to merge.

Kateryna Nezdolii added 2 commits June 13, 2019 17:01
Signed-off-by: Kateryna Nezdolii <nezdolik@spotify.com>
Signed-off-by: Kateryna Nezdolii <nezdolik@spotify.com>
@nezdolik nezdolik dismissed stale reviews from htuch and zuercher via 298dff7 June 13, 2019 15:59
@nezdolik
Copy link
Copy Markdown
Member Author

@rgs1 switched back to shared_ptr, ideally LbSubsetEntryPtr should be unique_ptr, not sure why it was declared shared in first place

@zuercher
Copy link
Copy Markdown
Member

@nezdolik if you can get that merge conflict fixed we can merge this (and then @snowp can merge his subset lb change).

Signed-off-by: Kateryna Nezdolii <nezdolik@spotify.com>
@nezdolik
Copy link
Copy Markdown
Member Author

@zuercher merge conflict should be fixed now

@zuercher zuercher merged commit 1a60b34 into envoyproxy:master Jun 14, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

subset load balancer optimize

6 participants