http: unified the filter chain creation in the FilterManager#37112
http: unified the filter chain creation in the FilterManager#37112wbpcode merged 12 commits intoenvoyproxy:mainfrom
Conversation
Signed-off-by: wangbaiping(wbpcode) <wangbaiping@bytedance.com>
Signed-off-by: wangbaiping(wbpcode) <wangbaiping@bytedance.com>
source/common/http/filter_manager.h
Outdated
| * explicitly. This only makes sense for upstream HTTP filter chain. | ||
| * | ||
| */ | ||
| CreateFilterChainResult createFilterChain(const FilterChainFactory& filter_chain_factory, |
There was a problem hiding this comment.
Can you comment a bit more about the motivation for this refactor?
Having a single createFilterChain function where one argument only works for downstream and one for upstream feels ugly. Why not retain createDownstream/createUpstream and only pass the relevant args?
/wait-any
There was a problem hiding this comment.
Can you comment a bit more about the motivation for this refactor?
/wait-any
The initial motivation is I wanna to refactor the http filter chain to use vector rather than list as the container of filters because the filter chain needn't O(1) modification anyway. And rather than ActiveStremDecoderFilterPtr, I want to use ActiveStremDecoderFilter directly. This could reduce unnecessary heap allocations.
This refactoring requires us to set filter callbacks at the end of filter chain creation. So I need to ensure the filter chain creation is under the control of FilterManager.
And even not for that, make sure all filter chain creation logic in same way is better choice.
Having a single createFilterChain function where one argument only works for downstream and one for upstream feels ugly. Why not retain createDownstream/createUpstream and only pass the relevant args?
Yeah, I can make the create filter chain a shared private method and create a wrapper method for upstream filter chain creation.
There was a problem hiding this comment.
I found I acutally needn't the upgrade option, because we can check whether the downstream stream callbacks is valid or not to determine to try upgrade or not.
Now, I removed it, code is cleaner now.
There was a problem hiding this comment.
By the way, after a check to the upstream filter chain creation, I think even only_create_if_configured is unnecessary. Rather add some specific logic/parameter to the FilterChainFactory.createFilterChain, it would be better to use a default FilterChainFactory instance. When no valid filters are provided by both router and cluster, then we can construct a default FilterChainFactory to create the filter chain. (Only contains UpstreamCodecFilter)
This way should be much cleaner.
(If it's ok to you, I can also do a minor refactoring to this with a new PR).
Signed-off-by: wangbaiping(wbpcode) <wangbaiping@bytedance.com>
alyssawilk
left a comment
There was a problem hiding this comment.
sorry about slow turnaround - was busy at EnvoyCon :-)
/wait
source/common/http/filter_manager.cc
Outdated
| return false; | ||
| } | ||
| bool upgrade_rejected = false; | ||
| FilterManager::CreateFilterChainResult |
There was a problem hiding this comment.
why change this one to CreateFilterChainResult? If it creates isn't the upgrade automatically not rejected? Seems simpler as a boolean
There was a problem hiding this comment.
source/common/http/filter_manager.cc
Outdated
| FilterManager::createFilterChain(const FilterChainFactory& filter_chain_factory, | ||
| bool only_create_if_configured) { | ||
| if (state_.created_filter_chain_) { | ||
| return {true, false}; |
There was a problem hiding this comment.
is this necessarily correct? Doesn't it depend on what happened previously? maybe at least comment if this is preserving legacy behavior
There was a problem hiding this comment.
Yeah, this is mainly for preserving legacy behavior. But I think you are right because the created_filter_chain_ flag only ensure we have created filter chain. Set the upgrade_rejected to false may be wrong. We may need other way to expose the upgrade failure.
There was a problem hiding this comment.
I found we have added a upgradeFilterChainCreated callback to expose/tell the success status of upgrade filter chain creation. This callabck typically could be reused to expose the failure status of upgrade filter chain creation. Then the createFilterChain() could only return a bool to tell if the filter chain is created or not.
| * Set up the Encoder/Decoder filter chain. | ||
| * @param filter_chain_factory the factory to create the filter chain. | ||
| * @param only_create_if_configured whether to only create the filter chain if it is configured | ||
| * explicitly. This only makes sense for upstream HTTP filter chain. |
There was a problem hiding this comment.
ooc is it ever not true for upstream filter chain? I'm wondering if we can infer this as we do the upgrade allowed option if they're just the inverse of each other
There was a problem hiding this comment.
ooc is it ever not true for upstream filter chain?
Yeah...it will be false when we try to create filters from router and cluster at second time. As I said before, i think we should remove this by providing a default filter chain factory for upstream filter chain.
There was a problem hiding this comment.
Would it be worth doing that now? default filter chain is just codec filter right?
There was a problem hiding this comment.
Would it be worth doing that now? default filter chain is just codec filter right?
I think it deserves. It not just make code simple also reduce memory overhead of cluster because we now need keep a default filter chain for every cluster.
Signed-off-by: wangbaiping(wbpcode) <wangbaiping@bytedance.com>
| State() | ||
| : codec_saw_local_complete_(false), codec_encode_complete_(false), | ||
| on_reset_stream_called_(false), is_zombie_stream_(false), successful_upgrade_(false), | ||
| is_internally_destroyed_(false), is_internally_created_(false), is_tunneling_(false), | ||
| decorated_propagate_(true), deferred_to_next_io_iteration_(false), | ||
| deferred_end_stream_(false) {} | ||
|
|
||
| // It's possibly for the codec to see the completed response but not fully | ||
| // encode it. | ||
| bool codec_saw_local_complete_ : 1; // This indicates that local is complete as the completed | ||
| // response has made its way to the codec. | ||
| bool codec_encode_complete_ : 1; // This indicates that the codec has | ||
| // completed encoding the response. | ||
| bool on_reset_stream_called_ : 1; // Whether the stream has been reset. | ||
| bool is_zombie_stream_ : 1; // Whether stream is waiting for signal | ||
| // the underlying codec to be destroyed. | ||
| bool successful_upgrade_ : 1; |
There was a problem hiding this comment.
These changes mainly used to fix clang.tidy.
There was a problem hiding this comment.
Hm. I think that removing the : 1 means that each of these fields will get 8x larger. What's the clang tidy error?
There was a problem hiding this comment.
Here is an example:
Use default member initializer for 'codec_saw_local_complete_' (fix available)clang-tidy(modernize-use-default-member-init)
There was a problem hiding this comment.
Hm. I think we'd prefer to avoid making this struct larger if we don't need to. Can you do a sizeof(State) before and after this change to see what it's doing? I wonder if we could use both : 1 and = false to get the best of both worlds?
There was a problem hiding this comment.
Yeah, you are right, it make the state memory footprint from 2 bytes to 11 bytes.
Although I am not sure if that make sense or not for software like envoy. we never pursue extreme low memory overhead.
But I still revert all these changes. I think @phlax is working on clang-tidy related things. we can do all these at there or change our clang-tidy rule. :)
alyssawilk
left a comment
There was a problem hiding this comment.
Sorry about all the back and forth - just trying to make sure as we move this we don't make the already confusing code more confusing. :-/
/wait
Never mind. Be careful to core code always make sense. :) |
Signed-off-by: wangbaiping(wbpcode) <wangbaiping@bytedance.com>
| * Set up the Encoder/Decoder filter chain. | ||
| * @param filter_chain_factory the factory to create the filter chain. | ||
| * @param only_create_if_configured whether to only create the filter chain if it is configured | ||
| * explicitly. This only makes sense for upstream HTTP filter chain. |
There was a problem hiding this comment.
Would it be worth doing that now? default filter chain is just codec filter right?
Signed-off-by: wangbaiping(wbpcode) <wangbaiping@bytedance.com>
RyanTheOptimist
left a comment
There was a problem hiding this comment.
Sorry for the delay. Overall this looks reasonable but a few comments. The optional<bool> in particular is a bit troublesome.
| State() | ||
| : codec_saw_local_complete_(false), codec_encode_complete_(false), | ||
| on_reset_stream_called_(false), is_zombie_stream_(false), successful_upgrade_(false), | ||
| is_internally_destroyed_(false), is_internally_created_(false), is_tunneling_(false), | ||
| decorated_propagate_(true), deferred_to_next_io_iteration_(false), | ||
| deferred_end_stream_(false) {} | ||
|
|
||
| // It's possibly for the codec to see the completed response but not fully | ||
| // encode it. | ||
| bool codec_saw_local_complete_ : 1; // This indicates that local is complete as the completed | ||
| // response has made its way to the codec. | ||
| bool codec_encode_complete_ : 1; // This indicates that the codec has | ||
| // completed encoding the response. | ||
| bool on_reset_stream_called_ : 1; // Whether the stream has been reset. | ||
| bool is_zombie_stream_ : 1; // Whether stream is waiting for signal | ||
| // the underlying codec to be destroyed. | ||
| bool successful_upgrade_ : 1; |
There was a problem hiding this comment.
Hm. I think that removing the : 1 means that each of these fields will get 8x larger. What's the clang tidy error?
Signed-off-by: wangbaiping(wbpcode) <wangbaiping@bytedance.com>
…nify-http-filter-chain
|
/retest |
Signed-off-by: wangbaiping(wbpcode) <wangbaiping@bytedance.com>
|
/retest |
Commit Message: http: unified the filter chain creation in the FilterManager
Additional Description:
This refactor ensure the all the http filter chain creation is done in the FilterManager. (This also make sure we can do more control to the filter chain creations.)
In the previous implementation, the
createFilterChainmethod (ofFilterManager) is only used by the downstream filter chain. And the upstream filter chain use another way to create filter chain. It make that it's hard to control the behavior of filter chain creation in uniform way.The
createFilterChainwill return a value to tell whether the upgrade is rejected. And useupgradeFilterChainCreatedcallback to tell whether the upgrade is accepted. If both are none, then, that means no upgrade.In the new implementation, we unified the way of filter chain creation. The
createFilterChainmethod will be used for both downstream and upstream. And a uniform way will be sued to report the upgrade results.Risk Level: mid.
Testing: n/a.
Docs Changes: n/a.
Release Notes: n/a.
Platform Specific Features: n/a.