-
Notifications
You must be signed in to change notification settings - Fork 4.8k
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
Wip: Add multi-connection support in H2 conn pool. #7852
Conversation
@mattklein123 @alyssawilk This is a first take on the issue #7403. |
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.
Thanks for taking this on. In order to aid in review, can you potentially add some high level comments for all the interfaces and functions in the header files? That will help me give some initial feedback on the implementation. Thank you!
/wait
@@ -646,6 +646,25 @@ using ProtocolOptionsConfigConstSharedPtr = std::shared_ptr<const ProtocolOption | |||
*/ | |||
class ClusterTypedMetadataFactory : public Envoy::Config::TypedMetadataFactory {}; | |||
|
|||
class ConnectionRequestPolicySubscriber { |
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.
Can you add interface comments for these classes and functions? It's not immediately clear to me why these policies need to live in upstream.h. Can we potentially move them to a new file? I'm not sure how they are going to get configured.
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 have added comments and TODOs hoping to make the intent clearer. There is no strong reason for having the policy interfaces in upstream.h
. The only reason i went with it for now is due to its proximity to ClusterInfo
. Since the policies are related (1:1) to ClusterInfo, they could be declared together. I am open to suggestions.
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.
OK thanks this is more clear. IMO I would simplify this for right now and not worry about a public interface, cluster info, etc. I would probably just build this config directly into the a new http2 connection pool options config:
envoy/api/envoy/api/v2/cds.proto
Line 252 in e03936e
core.Http2ProtocolOptions http2_protocol_options = 14; |
In terms of these interfaces and implementation, I would either just define them right now directly in the http2 conn pool code, or make new files in that area to contain them. We can always make this more generic later but IMO it's fine to define this where we are going to use this for now.
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.
@mattklein123 Thanks! How do you visualize the Htt2ConnectionPolicy
config? I suppose something like
clusters:
- name: cluster-name
connect_timeout: 0.25s
connection_policy:
max_requests_per_connection: 1
drain_on_overflow: yes // Should drain or keep in overflow list
idle_timeout: 500ms // Time after which the connection can be closed.
http2_protocol_options: {...}
...
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.
Something like this yes, but per @alyssawilk we should see if we can also unify with HTTP/1.
source/common/http/http2/conn_pool.h
Outdated
// list when drain clients does not have any more requests being served. | ||
// Connections remain in this list till: | ||
// - Connection is closed. | ||
std::list<ActiveClientPtr> to_close_clients_; | ||
ActiveClientPtr primary_client_; |
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.
Presumably primary/draining clients are no longer needed?
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.
That is correct. I will remove them.
@@ -651,6 +651,14 @@ ClusterInfoImpl::extensionProtocolOptions(const std::string& name) const { | |||
return nullptr; | |||
} | |||
|
|||
const ConnectionRequestPolicy& ClusterInfoImpl::connectionPolicy() const { | |||
if (!connection_policy_) { |
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 doubt this is thread safe? But it's clear to me yet where this is used and whether it needs to live here.
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.
Not in its current form. The idea is that the Policy implementation would be injected
but I am not sure how that would be implemented. I might need help with that.
Signed-off-by: Jojy G Varghese <[email protected]>
Signed-off-by: Jojy G Varghese <[email protected]>
Signed-off-by: Jojy G Varghese <[email protected]>
@mattklein123 PTAL. Thank you for initial feedback. Looking forward to more feedback. |
abfca1c
to
e266525
Compare
@mattklein123 I just rebased with master . I am getting link errors in protobuf:
Wondering what i am missing. |
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.
Thanks for working on this. This is going to need very detailed review, but in general this seems like it's on the right track. I think modulo my high level comments that I added, it's probably fine to start actually getting tests passing, add new tests, etc. Thank you!
/wait
@@ -646,6 +646,25 @@ using ProtocolOptionsConfigConstSharedPtr = std::shared_ptr<const ProtocolOption | |||
*/ | |||
class ClusterTypedMetadataFactory : public Envoy::Config::TypedMetadataFactory {}; | |||
|
|||
class ConnectionRequestPolicySubscriber { |
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.
OK thanks this is more clear. IMO I would simplify this for right now and not worry about a public interface, cluster info, etc. I would probably just build this config directly into the a new http2 connection pool options config:
envoy/api/envoy/api/v2/cds.proto
Line 252 in e03936e
core.Http2ProtocolOptions http2_protocol_options = 14; |
In terms of these interfaces and implementation, I would either just define them right now directly in the http2 conn pool code, or make new files in that area to contain them. We can always make this more generic later but IMO it's fine to define this where we are going to use this for now.
@@ -81,19 +94,63 @@ class ConnPoolImpl : public ConnectionPool::Instance, public ConnPoolImplBase { | |||
|
|||
virtual CodecClientPtr createCodecClient(Upstream::Host::CreateConnectionData& data) PURE; | |||
virtual uint32_t maxTotalStreams() PURE; | |||
/* |
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.
nit: please clean out the commented out code here and elsewhere.
// Connections that are waiting to be closed. Connections are moved to this | ||
// list when drain clients does not have any more requests being served. | ||
// Connections remain in this list till: | ||
// - Connection is closed. |
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.
Why is this state needed? Can't we just close them directly vs. putting them on a new list?
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 idea is that a busy/active
client could be transitioned to drained
if the policy dictates a) to not accept any more requests on that client b) close the client once all current requests are finished.
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.
Sorry I don't follow. Once a client can be closed why does it need to be on a list?
|
||
// Make sure all clients are destroyed before we are destroyed. | ||
ConnPoolImpl::~ConnPoolImpl() { | ||
drainConnections(); |
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.
All connections need to be closed here in this case like happened previously, not just put in the draining state.
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.
It happens in the method drainConnections
. It in turn calls checkForDrained
which then calls close
on all closable
clients. I thought once we move all the clients to drain
state, it implies that we dont accept any new requests and just wait for existing requests to finish .
@@ -259,17 +388,60 @@ void ConnPoolImpl::onStreamReset(ActiveClient& client, Http::StreamResetReason r | |||
} | |||
} | |||
|
|||
void ConnPoolImpl::onUpstreamReady() { | |||
// Establishes new codec streams for each pending request. | |||
while (!pending_requests_.empty()) { |
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.
In the HTTP/2 case I think we can still have multiple pending requests per connection created, right? Don't we still need a loop to deal with one we get a new connection?
@mattklein123 Thanks for reviewing. I wanted to check once again what i might be missing. After rebasing with master, i am unable to build:
it looks like a missing ldflag(libstdc++)? |
@conqerAtapple sorry not sure I would hop into #envoy-dev and ask there. cc @lizan @PiotrSikora |
@conqerAtapple make sure you have Bazel >= 0.28.0, ideally what |
- removed old commented reside - added override keyword. Signed-off-by: Jojy G Varghese <[email protected]>
@lizan thanks! that worked. |
* this interface as a contract between the policy implementation and policy | ||
* user(subscriber). | ||
*/ | ||
class ConnectionRequestPolicySubscriber { |
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 took a super cursory pass at this and while I'm really happy to get this work into HTTP/2 I'm worried about the code overlap between the HTTP/1 multiple-connection management and HTTP/2.
I think we might do better here if we tried to factor out / enhance the connection management we already have, and then use it in the H2 connection pool. WDYT?
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.
+1 to this. This was going to be my suggestion as well once we get the code a bit more stabilized. I think there will be significant duplication. Up to you whether you want to try to do it in HTTP/2 first and then figure out the overlap or try to factor out first... (There already is a common base class you can work from.)
- Added ConnectionPolicy interface in Mock. - Fixed conn pool cleanup. Signed-off-by: Jojy G Varghese <[email protected]>
This pull request has been automatically marked as stale because it has not had activity in the last 7 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
This pull request has been automatically marked as stale because it has not had activity in the last 7 days. It will be closed in 7 days if no further activity occurs. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
This pull request has been automatically closed because it has not had activity in the last 14 days. Please feel free to give a status update now, ping for review, or re-open when it's ready. Thank you for your contributions! |
Signed-off-by: Jojy G Varghese [email protected]
For an explanation of how to fill out the fields, please see the relevant section
in PULL_REQUESTS.md
Description: Currently H2 connection pool can create only ONE upstream connection. There are use cases that demand a policy based approach to connections in the H2 pool More background can be found at:
https://github.com/envoyproxy/envoy/issues/7403
The policy could be described as below example :
Risk Level: High
Testing: Unit tests, Integration tests to be added
Docs Changes: This change will require new configuration for describing the policy.
Release Notes:
[Optional Fixes #Issue]
[Optional Deprecated:]