-
Notifications
You must be signed in to change notification settings - Fork 5.3k
Description
Title: Redis prefixed routing
Description:
Hi friends, we'd be interested in adding prefix based routing to the redis proxy filter, but wanted to pitch the idea upstream to see the likelyhood of this feature beeing approved and get initial feedback before I jump into the implementation itself. Still very new to envoy, bare with me 😄
At Shopify we have multiple small pools of redises that we use for isolation purposes yet we would like to use a single envoy proxy (either as a k8s sidecar/daemonset) to connect to theses pools of redises. For example, shopify runs a massive pool of web workers to account for traffic spikes, yet all of the shops data is isolated into a shopify shard. In the event of massive traffic burst, this prevents a single shop from overloading possibly other stores redises and containing the blast radius to a small set of shops. In addition, prefix based routing would allow us to define pools that we can then scale independently by shard.
Similar to how facebook/mcrouter supports prefix routing, we would need a similar setup to route the keys to a specific cluster. This would allow the configuration of a single ingress, expose a single port, and let Envoy figure out which upstream pool it needs to route the keys.
An alternate approach with envoy would be to configure N redis-proxy filters to listen to N different ports, but this approach is not sustainable as every addition to one of the partition would require a restart of all the envoy proxies to expose the ports.
Proposition
Here's a rough draft of what I think the API could look like:
message RedisProxy {
message RouteMatch {
// If specified, the route is a prefix rule that must match the beginning of the keys. The proxy will always favor the longest matches.
string prefix = 1 [(validate.rules).string.min_bytes = 1];;
reserved 2; // regex based routing maybe?
// Indicates that prefix/path matching should be case insensitive. The default is true.
google.protobuf.BoolValue case_sensitive = 3;
}
message RouteAction {
// name of the upstream cluster
string cluster = 1 [(validate.rules).string.min_bytes = 1];
}
message Route {
// name of the route, used for instrumentation purposes
string name = 1;
RouteMatch match = 1 [(validate.rules).message.required = true, (gogoproto.nullable) = false];
RouteAction route = 2;
}
repeated Route routes = 3 [(gogoproto.nullable) = false];
// already existing parameter. This essentially becomes the equivalent of mcrouter "wildcard pool"
string cluster = 2 [(validate.rules).string.min_bytes = 1];
}The API is inspired quite a bit from the HTTP route configuration, albeit much simpler. I think initially a static list of routes would be sufficient and a next step would be to add RDS support. Much like mcrouter, envoy would not mutate the key (e.g. stripping the prefixes) when forwarding it upstream, but that could be added in the future if needed.
I'd be happy to help implementing this feature, any early feedback is very welcome 🙏