-
Notifications
You must be signed in to change notification settings - Fork 5.5k
redis: prefixed routing #5658
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
redis: prefixed routing #5658
Changes from 14 commits
a36017e
de88470
da0e958
3b12bcb
0fde3aa
164159f
36b5ee2
74c2248
8dd1e5f
0b8e861
ce5b011
b34640e
2168949
71e619e
2625680
5f9cbc9
9abb8f9
c6d6cc8
ab39fee
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -22,7 +22,13 @@ message RedisProxy { | |
| // Name of cluster from cluster manager. See the :ref:`configuration section | ||
| // <arch_overview_redis_configuration>` of the architecture overview for recommendations on | ||
| // configuring the backing cluster. | ||
| string cluster = 2 [(validate.rules).string.min_bytes = 1]; | ||
| // | ||
| // .. attention:: | ||
| // | ||
| // This field is deprecated. Use a :ref:`catch-all | ||
| // route<envoy_api_field_config.filter.network.redis_proxy.v2.RedisProxy.PrefixRoutes.catch_all_cluster>` | ||
| // instead. | ||
| string cluster = 2 [deprecated = true]; | ||
|
|
||
| // Redis connection pool settings. | ||
| message ConnPoolSettings { | ||
|
|
@@ -48,10 +54,60 @@ message RedisProxy { | |
| bool enable_hashtagging = 2; | ||
| } | ||
|
|
||
| // Network settings for the connection pool to the upstream cluster. | ||
| // Network settings for the connection pool to the upstream clusters. | ||
| ConnPoolSettings settings = 3 [(validate.rules).message.required = true]; | ||
|
|
||
| // Indicates that latency stat should be computed in microseconds. By default it is computed in | ||
| // milliseconds. | ||
| bool latency_in_micros = 4; | ||
|
|
||
| message PrefixRoutes { | ||
| message Route { | ||
| // String prefix that must match the beginning of the keys. Envoy will always favor the | ||
| // longest match. | ||
| string prefix = 1 [(validate.rules).string.min_bytes = 1]; | ||
|
|
||
| // Indicates if the prefix needs to be removed from the key when forwarded. | ||
| bool remove_prefix = 2; | ||
|
|
||
| // Upstream cluster to forward the command to. | ||
| string cluster = 3; | ||
| } | ||
|
|
||
| // List of prefix routes. | ||
| repeated Route routes = 1 [(gogoproto.nullable) = false]; | ||
|
|
||
| // Indicates that prefix matching should be case insensitive. | ||
| bool case_insensitive = 2; | ||
|
|
||
| // Optional catch-all route to forward commands that doesn't match any of the routes. The | ||
| // catch-all route becomes required when no routes are specified. | ||
| string catch_all_cluster = 3; | ||
| } | ||
|
|
||
| // List of **unique** prefixes used to separate keys from different workloads to different | ||
| // clusters. Envoy will always favor the longest match first in case of overlap. A catch-all | ||
| // cluster can be used to forward commands to when there is no match. Time complexity of the | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. nit: s/to when/when |
||
| // lookups are in O(min(longest key prefix, key length)). | ||
| // | ||
| // Example: | ||
| // | ||
| // .. code-block:: yaml | ||
| // | ||
| // prefix_routes: | ||
| // routes: | ||
| // - prefix: "ab" | ||
| // cluster: "cluster_a" | ||
| // - prefix: "abc" | ||
| // cluster: "cluster_b" | ||
| // # next 2 lines will break uniqueness constraint | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would probably delete this. I think the error message generated would be obvious. |
||
| // # - prefix: "abc" | ||
| // # cluster: "cluster_c" | ||
| // - prefix: "a" | ||
| // cluster: "cluster_d" | ||
| // | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you add further text to the example along the lines of "When using the above routes, the following prefixes would be sent to: ..." (With some examples) |
||
| // See the :ref:`configuration section | ||
| // <arch_overview_redis_configuration>` of the architecture overview for recommendations on | ||
| // configuring the backing clusters. | ||
| PrefixRoutes prefix_routes = 5 [(gogoproto.nullable) = false]; | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -568,8 +568,9 @@ template <class Value> struct TrieLookupTable { | |
| * Adds an entry to the Trie at the given Key. | ||
| * @param key the key used to add the entry. | ||
| * @param value the value to be associated with the key. | ||
| * @return false when a value already exists for the given key. | ||
| */ | ||
| void add(const char* key, Value value) { | ||
| bool add(const char* key, Value value) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please add some explicit unit tests for the functions in this file. |
||
| TrieEntry<Value>* current = &root_; | ||
| while (uint8_t c = *key) { | ||
| if (!current->entries_[c]) { | ||
|
|
@@ -578,7 +579,11 @@ template <class Value> struct TrieLookupTable { | |
| current = current->entries_[c].get(); | ||
| key++; | ||
| } | ||
| if (current->value_) { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This might change the behavior for current callers. Should |
||
| return false; | ||
| } | ||
| current->value_ = value; | ||
| return true; | ||
| } | ||
|
|
||
| /** | ||
|
|
@@ -599,6 +604,31 @@ template <class Value> struct TrieLookupTable { | |
| return current->value_; | ||
| } | ||
|
|
||
| /** | ||
| * Finds the entry associated with the longest prefix. Complexity is O(min(longest key prefix, key | ||
| * length)) | ||
| * @param key the key used to find. | ||
| * @return the value matching the longest prefix based on the key. | ||
| */ | ||
| Value findPrefix(const char* key) const { | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| const TrieEntry<Value>* current = &root_; | ||
| const TrieEntry<Value>* result = nullptr; | ||
| while (uint8_t c = *key) { | ||
| if (current->value_) { | ||
| result = current; | ||
| } | ||
|
|
||
| // https://github.com/facebook/mcrouter/blob/master/mcrouter/lib/fbi/cpp/Trie-inl.h#L126-L143 | ||
| current = current->entries_[c].get(); | ||
| if (current == nullptr) { | ||
| return result ? result->value_ : nullptr; | ||
| } | ||
|
|
||
| key++; | ||
| } | ||
| return current ? current->value_ : result->value_; | ||
| } | ||
|
|
||
| TrieEntry<Value> root_; | ||
| }; | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should this have a min-length validation?