Support multiple hash policies for HTTP routing#1756
Support multiple hash policies for HTTP routing#1756mattklein123 merged 10 commits intoenvoyproxy:masterfrom
Conversation
Fixes envoyproxy#1422 Signed-off-by: Alex Konradi <akonradi@google.com>
source/common/router/config_impl.h
Outdated
| Optional<uint64_t> generateHash(const std::string& downstream_addr, | ||
| const Http::HeaderMap& headers) const override; | ||
|
|
||
| class HashImpl { |
There was a problem hiding this comment.
If this is a pure interface, it probably belongs in include/envoy/router. Also, for conventions, we tend not to suffix pure interfaces with Impl.
There was a problem hiding this comment.
My thought was that it's part of HashPolicyImpl's implementation, not part of its publicly accessible API. I'll change "HashImpl" to "HashMethod"; the intent was to signify that this is an interface for various ways of producing a hash.
source/common/router/config_impl.cc
Outdated
| for (const HashImplPtr& hash_impl : hash_impls_) { | ||
| Optional<uint64_t> new_hash = hash_impl->evaluate(downstream_addr, headers); | ||
| if (new_hash.valid()) { | ||
| hash.value(hash.valid() ? (hash.value() ^ new_hash.value()) : new_hash.value()); |
There was a problem hiding this comment.
You might want something like a shift + XOR or multiplication (I don't think performance is a big issue here, it's a few cycles more). Otherwise, you can get degenerate situations, for example the same hash policy repeated twice, which will just give you zero always.
source/common/router/config_impl.cc
Outdated
| } | ||
| break; | ||
| default: | ||
| ASSERT(false); |
There was a problem hiding this comment.
Might consider moving to throwing an EnvoyException here. I was a bit lazy initially as I expected to fill in all cases (or have constraints to cover them), but if we're writing new code, we should either add a TODO about using constraints to catch this/implement or throw.
| if (header) { | ||
| hash.value(HashUtil::xxHash64(header->value().c_str())); | ||
| } | ||
| return hash; |
There was a problem hiding this comment.
Is it worth the complexity to have this optional? Why not just return a zero hash value if missing?
There was a problem hiding this comment.
My intent was to remain compatible with the existing interface. Zero is a valid hash value, even if it doesn't show up often.
source/common/router/config_impl.cc
Outdated
| public: | ||
| IpHashImpl() {} | ||
|
|
||
| ~IpHashImpl() override {} |
There was a problem hiding this comment.
Don't need to override these if default.
Signed-off-by: Alex Konradi <akonradi@google.com>
Signed-off-by: Alex Konradi <akonradi@google.com>
Signed-off-by: Alex Konradi <akonradi@google.com>
This prevents the degenerate case that htuch mentioned, where a duplicated hash policy would cancel out the first one. Signed-off-by: Alex Konradi <akonradi@google.com>
Signed-off-by: Alex Konradi <akonradi@google.com>
source/common/router/config_impl.cc
Outdated
| if (header) { | ||
| hash.value(HashUtil::xxHash64(header->value().c_str())); | ||
| for (const HashMethodPtr& hash_impl : hash_impls_) { | ||
| Optional<uint64_t> new_hash = hash_impl->evaluate(downstream_addr, headers); |
| } | ||
| EXPECT_NE(hash_ip, hash_h); | ||
| EXPECT_NE(hash_ip, hash_both); | ||
| EXPECT_NE(hash_h, hash_both); |
There was a problem hiding this comment.
What about validating that if you hash twice the same input, you get a deterministic result, i.e. eq?
source/common/router/config_impl.cc
Outdated
| } | ||
|
|
||
| private: | ||
| Http::LowerCaseString header_name_; |
| break; | ||
| default: | ||
| throw EnvoyException( | ||
| fmt::format("Unsupported hash policy {}", hash_policy.policy_specifier_case())); |
mattklein123
left a comment
There was a problem hiding this comment.
Generally looks good apart from @htuch comments and my small one.
source/common/router/config_impl.cc
Outdated
| for (const HashMethodPtr& hash_impl : hash_impls_) { | ||
| Optional<uint64_t> new_hash = hash_impl->evaluate(downstream_addr, headers); | ||
| if (new_hash.valid()) { | ||
| hash.value(hash.valid() ? (((hash.value() << 1) | (hash.value() >> 63)) ^ new_hash.value()) |
There was a problem hiding this comment.
can you add a comment on how this bit shifting was chosen?
Signed-off-by: Alex Konradi <akonradi@google.com>
Signed-off-by: Alex Konradi <akonradi@google.com>
Signed-off-by: Alex Konradi <akonradi@google.com>
|
Sorry please merge master again. Still trying to sort out CI issues. |
…iple-hashes Signed-off-by: Alex Konradi <akonradi@google.com>
Fixes envoyproxy#1422 Signed-off-by: Alex Konradi <akonradi@google.com>
Description: Adding these has had no measurable benefit, and they're likely detrimental to timely passive healthchecking and interactions tuned for specific TCP keepalive settings. Risk Level: Low Testing: Local & CI Signed-off-by: Mike Schore <mike.schore@gmail.com> Signed-off-by: JP Simard <jp@jpsim.com>
Description: Adding these has had no measurable benefit, and they're likely detrimental to timely passive healthchecking and interactions tuned for specific TCP keepalive settings. Risk Level: Low Testing: Local & CI Signed-off-by: Mike Schore <mike.schore@gmail.com> Signed-off-by: JP Simard <jp@jpsim.com>
**Description** This commit cleans up Makefile by removing unnecessary variables etc. Signed-off-by: Takeshi Yoneda <t.y.mathetake@gmail.com>
Fixes #1422