Skip to content
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

Mark HTTP/2 connection as closing on exception caught #2686

Merged
merged 5 commits into from
Oct 18, 2023

Conversation

idelpivnitskiy
Copy link
Member

@idelpivnitskiy idelpivnitskiy commented Sep 1, 2023

Motivation:

Similar to #2675, H2ParentConnectionContext.AbstractH2ParentConnection should mark the Channel as closing on exceptionCaught. If there is no active Subscriber, it should enforce channel closure using ChannelCloseUtils.
In case users don't have offloading, there is a risk to retry on the same IO thread. We should notify LoadBalancer that this connection is closing to avoid retrying on the same connection.

Modifications:

  • Invoke parentContext.notifyOnClosingImpl() inside exceptionCaught before notifying transportError and failing subscriber;
  • Close the h2 channel if there is no active Subscriber to consume the error;
  • Remove H2ParentConnectionContext.hasSubscriber() that does not seem required anymore;
  • Enhance ConnectionClosedAfterIoExceptionTest to make sure we fail only the first connect attempt, we capture RetryableExceptions, and capture the callers stack trace if client.request(...) fails;

Result:

Retries always select a different connection if existing connection observes an exception.
Fixes #2685.

@idelpivnitskiy idelpivnitskiy self-assigned this Sep 1, 2023
@idelpivnitskiy idelpivnitskiy marked this pull request as ready for review September 1, 2023 16:49
@idelpivnitskiy idelpivnitskiy marked this pull request as draft September 1, 2023 20:24
@idelpivnitskiy
Copy link
Member Author

CI shows that H2PriorKnowledgeFeatureParityTest > serverGracefulClose is failing, but I can not reproduce it locally. Will dig deeper next week.

Motivation:

Similar to apple#2675, `H2ParentConnectionContext.AbstractH2ParentConnection`
should mark the `Channel` as closing on `exceptionCaught`. If there is
no active `Subscriber`, it should enforce channel closure using
`ChannelCloseUtils`.
In case users don't have offloading, there is a risk to retry on the
same IO thread. We should notify `LoadBalancer` that this connection is
closing to avoid retrying on the same connection.

Modifications:

- Invoke `parentContext.notifyOnClosing()` inside `exceptionCaught`
before notifying `transportError` and failing subscriber;
- Close the h2 channel if there is no active `Subscriber` to consume the
error;
- Remove `H2ParentConnectionContext.notifyOnClosingImpl()` that does not
seem required anymore;
- Enhance `ConnectionClosedAfterIoExceptionTest` to make sure we fail
only the first connect attempt, we capture `RetryableException`s, and
capture the callers stack trace if `client.request(...)` fails;

Result:

Retries always select a different connection if existing connection
observes an exception.
Fixes apple#2685.
@idelpivnitskiy idelpivnitskiy marked this pull request as ready for review October 13, 2023 17:03
* This method is required to access notifyOnClosing() from AbstractH2ParentConnection, because usage of
* {@code parentContext.notifyOnClosing()} directly triggers {@link java.lang.IllegalAccessError}.
*/
private void notifyOnClosingImpl() {
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Removal of this method was the cause for H2PriorKnowledgeFeatureParityTest > serverGracefulClose failures 🤦
I'm not sure why Intellij IDEA or javac could not catch this as a problem.

    java.lang.BootstrapMethodError: java.lang.IllegalAccessError: tried to access method io.servicetalk.transport.netty.internal.NettyChannelListenableAsyncCloseable.notifyOnClosing()V from class io.servicetalk.http.netty.H2ParentConnectionContext$AbstractH2ParentConnection
    	at io.servicetalk.http.netty.H2ParentConnectionContext$AbstractH2ParentConnection.channelRead(H2ParentConnectionContext.java:291) ~[servicetalk-http-netty-0.42.39-SNAPSHOT.jar:?]

@idelpivnitskiy idelpivnitskiy requested a review from daschl October 16, 2023 17:02
Copy link
Contributor

@daschl daschl left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM (but you may want another pair of eyes who is more familiar with the H2 intrinsic behavior)

Copy link
Member

@Scottmitch Scottmitch left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

quick peek, 1 question, lgtm

cause = wrapIfNecessary(cause);
if (observer != NoopConnectionObserver.INSTANCE) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume this is done at a higher level now?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It will be done a couple lines below. Either tryFailSubscriber or ChannelCloseUtils will assign a connection error before closing the channel.

@idelpivnitskiy idelpivnitskiy merged commit f2fbd46 into apple:main Oct 18, 2023
15 checks passed
@idelpivnitskiy idelpivnitskiy deleted the h2-onClosing branch October 18, 2023 16:23
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

ConnectionClosedAfterIoExceptionTest failure
3 participants