-
Notifications
You must be signed in to change notification settings - Fork 273
VHost/Route-local filter configurations #605
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
Conversation
Signed-off-by: Chris Roche <croche@lyft.com>
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.
LGTM. @htuch @lizan @rshriram @kyessenov for further review.
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.
LGTM
envoy/api/v2/route/route.proto
Outdated
// The per_filter_config field can be used to provide virtual host-specific | ||
// configurations for filters. The key should match the filter name, such as | ||
// *envoy.buffer* for the HTTP buffer filter. Use of this field is filter | ||
// specific; see the HTTP filter documentation for if and how it is utilized. |
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.
Need a link here to the docs.
envoy/api/v2/route/route.proto
Outdated
// The per_filter_config field can be used to provide route-specific | ||
// configurations for filters. The key should match the filter name, such as | ||
// *envoy.buffer* for the HTTP buffer filter. Use of this field is filter | ||
// specific; see the HTTP filter documentation for if and how it is utilized. |
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.
Same.
Signed-off-by: Chris Roche <croche@lyft.com>
@htuch ref links added. LMK if there's anything else. |
// *envoy.buffer* for the HTTP buffer filter. Use of this field is filter | ||
// specific; see the :ref:`HTTP filter documentation <config_http_filters>` | ||
// for if and how it is utilized. | ||
map<string, google.protobuf.Struct> per_filter_config = 12; |
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.
Suggest to add another map:
// map of filter name to filter config sha of SHA(seriazlized_per_filter_config).
map<string, string> per_filter_config_sha = 13;
Some filters need to pre-process the filter config. This sha can be used to skip the pre-process step if fitler_config is not changed.
if (sha != old_saved_sha) {
obj = pre_process_config(config_data);
}
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.
The question is do we want to do this for all filters universally? I don't have strong opinion on this. The filter can do this kind of SHA cache inside the Struct.
If so, define another
message CachableFilterConfig {
string sha = 1;
Struct config = 2;
}
And then use the message as map value.
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.
The benefit of using a separate map is:
only the filters wanted to have this optimization need to fill in the sha map.
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.
Even if we wanted to add the SHA map (and I'm not sure I agree it's worth the complexity), I'm not sure how it would be used unless we make the Envoy side feature a lot more complicated. Basically, since this information is delivered over RDS, it's going to be in the route table, and orthogonal from the filter. The filter will just be able to look up the proto and dynamic_cast it from the route. So I don't think any kind of SHA will really help here? What did you have in mind?
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.
I think this doesn't belong in the initial version. We can always add it later. Also, hashing isn't that expensive. The filter can just compute the xxHash
or whatevs.
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.
Agreed. @qiwzhang can you open a new issue on the SHA stuff? Again I don't really understand how it would work at the route level in any case.
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.
I like to clarify how per_route_config_sha can be used.
A filter needs to preprocess the per_route_config.
obj = pre_process(pre_route_config);
Such pre-processing can be slow, it should NOT be performed for each request. One way to optimize it is to save the preprocessed "obj" in some global config. When a request comes, the filter just needs to detect if per_route_config has been changed. Without "sha" map, the filter needs to serialize the proto and sha it to detect the config change. If per-route config is big, these two steps can be slow too.
Another option is to add a new function in FilterFactory
void setRouteConfig(string unique_route_id, Struct config) PURE;
This function will be called when RDS receives new route tables, This will give filter chance to preprocess per_route config and save the pre-processed obj into its global map (not pre-request).
as global_map[ route_id ] = obj;
During request, obj can be retrieved as
obj = global_map[ filter_callback->route()->unique_route_id() ];
This is better than first approach, the pre-process is done in the config thread, not at worker thread.
Agreed that, such optimization can be done in the later phase.
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.
Yeah if we do this we need a new filter factory function. Can we please treat this as a different feature request? I would open an issue on this. We don't need this at Lyft and I would like to move this along for the basis use case.
Also, per @htuch in general you can just hash the proto which is what we do in a lot of other places.
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.
Created envoyproxy/envoy#3008 to track this
@rodaine I suggest adding this to weighted clusters as well, so that we can merge @yuval-k 's usecase as well and we can merge the two implementations (envoyproxy/envoy#3003) |
@rshriram agreed, if we already need this per the other PR, let's just add it to weighted clusters now. |
If we add per_filter_config to route action and weighted clusters, how will we access it from the filter code? will it be exposed on I know this is an implementation detail and the reason I'm bringing this up is because I think it presents a trade-off:
If we want it available on both, we might want to consider different names to avoid confusion. |
Signed-off-by: Chris Roche <croche@lyft.com>
@rshriram added to @yuval-k I haven't dug in deep enough to the implementation yet to answer your question specifically, but the field is added to the Route not |
That's true for RouteAction; |
Talked offline with @yuval-k to clarify the implementation plan. TL;DR: the |
@rodaine @yuval-k have you considered merging these so we have just a single config to worry about? I think it would be best to avoid having lots of cases in filters which look like "First check if the config is in the vhost, then in the route, then in the cluster", where you mostly just want a unified effective config based on the selected vhost/route/cluster. |
@htuch the problem I see with merging is that w.cluster (and hence its config) are available from |
IMO it should be up to the filter to decide what they do w/ the vhost vs. route data. I suppose we could have a different accessor on the route which also returns already merged protos? But that is more of an Envoy side detail. |
They don't need to be mutually exclusive. We can provide the methods for folks to access the route/vhost/w.cluster configs individually at first and also offer a merged config that rolls them all up. |
@rodaine sorry that's exactly what I meant. |
OK, that makes sense, let's go with this proposal then. |
@@ -197,6 +212,13 @@ message WeightedCluster { | |||
// :ref:`cluster_metadata <envoy_api_field_route.RouteAction.cluster_metadata>` from the | |||
// enclosing :ref:`envoy_api_msg_route.RouteAction`. | |||
core.Metadata cluster_metadata = 7; | |||
|
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.
Are we going to rollback cluster_metadata?
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.
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.
yes, That's correct; once this is merged.
@rshriram can I get an approval from your end and then we can merge? |
This patch begins addressing #540, adding
per_filter_config
fields to bothVirtualHost
andRoute
configs. A following PR will, as an initial PoC/example, implement vhost/route specific configs for the HTTP buffer filter.