Add perFilerConfigObject to store pre-processed per-route-config#3128
Add perFilerConfigObject to store pre-processed per-route-config#3128ggreenway merged 3 commits intoenvoyproxy:masterfrom
Conversation
|
@mattklein123 @rodaine, could you help to review this? Thanks |
include/envoy/router/router.h
Outdated
There was a problem hiding this comment.
I think this can be named "PerRouteConfig", or maybe "RouteSpecificConfig". Or "RouteSpecificFilterConfig".
There was a problem hiding this comment.
I would vote for "RouteSpecificFilterConfig" but I don't feel that strongly about it.
There was a problem hiding this comment.
Now, this is going to be painful isn't it? Every filter will now have two config objects in some sense. a preprocessed per-route thing and a filter level config object. I guess thats okay, given that the perf benefit
There was a problem hiding this comment.
Every filter is basically doing this today, and it's entirely optional, so it seems OK to me?
include/envoy/server/filter_config.h
Outdated
There was a problem hiding this comment.
Style: delete this line, change previous line to createPerRouteConfigObject(const Protobuf::Message&) {
source/common/router/config_impl.cc
Outdated
There was a problem hiding this comment.
style: methods get camelCase, not snake_case
source/common/router/config_impl.cc
Outdated
There was a problem hiding this comment.
nit: I'd name this "it" or "iterator"
include/envoy/router/router.h
Outdated
There was a problem hiding this comment.
I think we should add an additional template method:
template <typename Derived>
const Derived* perFilterConfigObjectTyped(const std::string& name) const {
const PerRouteConfigObject* obj = perFilterConfigObject(name);
if (obj == nullptr) {
return obj;
}
ASSERT(dynamic_cast<const Derived*>(obj) != nullptr);
return static_cast<const Derived*>(obj);
}
Or similar.
There was a problem hiding this comment.
Yeah we have basically this for TLS. +1
mattklein123
left a comment
There was a problem hiding this comment.
In general love this approach. Thanks @qiwzhang. cc @rodaine @rshriram this will allow you to trivially improve the perf of your filters? Should we wait until this lands?
I actually wonder if we should just kill the other functions and only have this type of config. If the filter just wants the proto they can just store it in a wrapper? WDYT?
include/envoy/router/router.h
Outdated
There was a problem hiding this comment.
I would vote for "RouteSpecificFilterConfig" but I don't feel that strongly about it.
include/envoy/router/router.h
Outdated
There was a problem hiding this comment.
Yeah we have basically this for TLS. +1
source/common/router/config_impl.cc
Outdated
There was a problem hiding this comment.
nit: Use ternary operator here. Can you fix other cases of this? I think @rodaine might have another one that I didn't comment on.
|
As an aside, I don't think this solution will work for Lua which is more complicated. This is because the Lua code must be JITd per-thread and can't be constant global like this data. I will think about about the Lua case but I think we can probably proceed with this as it's blocking a few things. |
|
@mattklein123 for Lua, could the config object own a TLS slot, and store the Lua state in that? Might have to make this non-const, but that wouldn't substantially change the approach. |
+1 to that. |
include/envoy/router/router.h
Outdated
There was a problem hiding this comment.
IF we are going down the path of merging with perFilterConfig, I would kill this function and change signature of the other..
rshriram
left a comment
There was a problem hiding this comment.
This is nice.. as noted earlier, just change the signature of the existing function (perFilterConfig) to return the wrapper object you have instead of proto message.
|
yeah +1 to @rshriram suggestion. We can hold on the fault/buffer PRs until we finish this.
Yes, that should work. The only downside to that approach is we would need a TLS slot per route which might be inefficient in the case where we have lots of routes, but, I think that's probably an edge case. IMO I would just leave the signature as const for now since the wrapper really does have to be const. If the implementation does non-const/mutable things under the hood in special cases that's probably OK... |
rodaine
left a comment
There was a problem hiding this comment.
Awesome! Agreed with @rshriram and @mattklein123, let's just replace the existing perFilterConfig methods.
include/envoy/router/router.h
Outdated
|
Thanks for the review. Here is my plan:
Router::RouteSpecificFilterConfigConstSharedPtr
templated function as Thanks |
|
PTAL |
|
I will review tomorrow, but @ggreenway @rshriram I don't think this by itself will work for Lua. The reason being that in order to use TLS and more complicated things, the factory will need access to the FactoryContext. @ggreenway this bring us back full circle and I think we will need to provide the full FactoryContext all the way to the route config, or think of some other cleaner callback way of getting it in. I would still suggest we just get this in as is and we can figure out the Lua (and maybe WebSocket case after). |
mattklein123
left a comment
There was a problem hiding this comment.
LGTM, just some small nits. I think we can sort out the Lua case later.
include/envoy/router/router.h
Outdated
There was a problem hiding this comment.
This entire function can be simplified to:
return dynamic_cast<const Derived*>(perFilterConfig(name));
We need to do the real dynamic_cast for correctness, and it's fine to dynamic_cast nullptr. Same for the other spots.
include/envoy/router/router.h
Outdated
There was a problem hiding this comment.
"If there is no per-filter config..." (same below)
include/envoy/router/router.h
Outdated
There was a problem hiding this comment.
"or the filter factory returns nullptr, ..." (same below)
include/envoy/server/filter_config.h
Outdated
There was a problem hiding this comment.
"will be stored in the loaded route configuration."
include/envoy/server/filter_config.h
Outdated
There was a problem hiding this comment.
nit: return {} or return nullptr should work
Signed-off-by: Wayne Zhang <qiwzhang@google.com>
Signed-off-by: Wayne Zhang <qiwzhang@google.com>
Signed-off-by: Wayne Zhang <qiwzhang@google.com>
mattklein123
left a comment
There was a problem hiding this comment.
LGTM, thanks. @ggreenway if this works for you can you approve/merge?
|
Question: can we get similar functionality for tcp ? |
|
I don’t know what gets carried through from SNI filter chain match. |
|
@rshriram for tcp, routes will be defined by the FilterChainMatch, so each route will have a completely independent filter-chain (with config) anyways, so no additional work will be needed. |
| virtual ProtobufTypes::MessagePtr createEmptyRouteConfigProto() { | ||
| return createEmptyConfigProto(); | ||
| virtual Router::RouteSpecificFilterConfigConstSharedPtr | ||
| createRouteSpecificFilterConfig(const ProtobufWkt::Struct&) { |
There was a problem hiding this comment.
I would strongly -1 to exposing Struct to filter interface and in favor of wrapping them in an interface like #3109 did. Hiding Struct from filter interface is important when we see scaling issues with the config and want to migrate to Any (via oneof) in future, as mentioned in https://github.com/envoyproxy/data-plane-api/issues/540#issuecomment-373250850 . cc @htuch.
Description:
Add a new function in filter_factory to allow filter to generate a pre-processed object for per-filter-config.
In VHost, Route, and RouteEntry, add a new function perFilterConfigObject to retrieve this pre-processed object.
Risk Level: Low