-
Notifications
You must be signed in to change notification settings - Fork 1.9k
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
Jetty client is not responding to GO_AWAY packet received from (Jetty) Server and continue to send traffic on same connection #8678
Comments
Jetty 9.x is now at End of Community Support. Does this happen with Jetty 10.x? |
Our application is supported on Java 8.x , whereas Jetty 10.x requires Java 11.x so didn't tried on it. Thanks !! |
@praveenchandna see #5310. Jetty is now following the HTTP/2 specification more closely, so Envoy sending a "graceful" GOAWAY must not be replied yet, until Envoy sends a final GOAWAY, which Jetty's client replies to. The behavior you see is correct. |
Hi @sbordet Thanks for your reply. Checked the issue #5310, and what we observe is similar, but the issue in our scenario is on top of that. As you said, the following is the order:
This is as per the HTTP/2 specification also: Here as per the specification, Jetty client is not sending the requests to Envoy post receiving the graceful GO_AWAY frame. Now the issue: As per the specification: But Jetty client is trying to send the request on that connection (marked as REMOTELY_CLOSED). Isn't the connection with state marked as REMOTELY_CLOSED, only be used to receive response of streams sent before the graceful GO_AWAY frame, and new connection should be created at the time a new request is received? |
@prathamk I see your point, we will look into it. |
Hello @sbordet , Thanks for your reply. Thanks !! |
@praveenchandna There is a chance that it may be addressed in 9.4.x, but it is unlikely as that release branch is no longer actively maintained for community issues. |
@praveenchandna unfortunately I don't think this problem is solvable as it is inherently racy. The client may acquire a connection which is still open, but before it actually gets the chance to send a request, the server will send the graceful GOAWAY and possibly also the normal GOAWAY. This is a generic problem also in HTTP/1.1 where the server could close the connection exactly when the client is about to send the request. The only thing that we can do is to try to reduce the window of this race happening, but I'm not sure it's worth it. Alternatively, if you know that the server is closing the connection either after a number of requests or after a fixed time, you can configure the client pool to close the connection before the server does. |
Can you share configuration snippets to achieve this? |
HttpClientTransport transport = new HttpClientTransportOverHTTP2(http2Client);
transport.setConnectionPoolFactory(destination -> {
HttpClient httpClient = destination.getHttpClient();
MultiplexConnectionPool pool = new MultiplexConnectionPool(destination, httpClient.getMaxConnectionsPerDestination(), destination, httpClient.getMaxRequestsQueuedPerDestination());
// A connection won't be used after 100 request/response cycles.
pool.setMaxUsageCount(100);
// Alternatively.
// A connection won't be used after 2 minutes of usage.
pool.setMaxDuration(120000);
}); Remember that in order to use any of these 2 mechanisms effectively, you have to somehow know that the server won't close before (or that it would be a very rare case that the server closes before). Even if you're using the mechanisms above, I would still configure the client with a smaller idle timeout than the server. |
Hi @sbordet Thanks for your reply.
Yes, to proceed around this issue, we have implemented the same behavior as you have mentioned in Jetty code. The inherent race condition is still there, but failures have been drastically reduced. Previously where we had failures somewhere around 35000, now there are failures somewhere around 10. So there is some benefit to it, if not 100%.
Unfortunately, in our scenario, this is not known. |
@prathamk do you want to submit a pull request with your changes? |
…fic on same connection * Now upon receiving the GOAWAY, the connection is removed from the pool, so it cannot be used by new requests. * HTTP2Session.removeStream() now happens _after_ notifying HEADERS and DATA events, although the Stream state change still happens before. This is necessary to avoid that a "close" event is notified before a "headers" or "data" event. With these changes, the race window of a client acquiring a connection while the server is closing it is reduced, but it is impossible to close it completely. Signed-off-by: Simone Bordet <[email protected]>
…fic on same connection * Now upon receiving the GOAWAY, the connection is removed from the pool, so it cannot be used by new requests. * HTTP2Session.removeStream() now happens _after_ notifying HEADERS and DATA events, although the Stream state change still happens before. This is necessary to avoid that a "close" event is notified before a "headers" or "data" event. With these changes, the race window of a client acquiring a connection while the server is closing it is reduced, but it is impossible to close it completely. Signed-off-by: Simone Bordet <[email protected]> (cherry picked from commit fbc23ac)
…fic on same connection (#8894) * Now upon receiving the GOAWAY, the connection is removed from the pool, so it cannot be used by new requests. * HTTP2Session.removeStream() now happens _after_ notifying HEADERS and DATA events, although the Stream state change still happens before. This is necessary to avoid that a "close" event is notified before a "headers" or "data" event. With these changes, the race window of a client acquiring a connection while the server is closing it is reduced, but it is impossible to close it completely. Signed-off-by: Simone Bordet <[email protected]> (cherry picked from commit fbc23ac)
…fic on same connection (#8891) * Fixes #8678 - Jetty client receives GO_AWAY and continue to send traffic on same connection * Now upon receiving the GOAWAY, the connection is removed from the pool, so it cannot be used by new requests. * HTTP2Session.removeStream() now happens _after_ notifying HEADERS and DATA events, although the Stream state change still happens before. This is necessary to avoid that a "close" event is notified before a "headers" or "data" event. With these changes, the race window of a client acquiring a connection while the server is closing it is reduced, but it is impossible to close it completely. Signed-off-by: Simone Bordet <[email protected]>
@sbordet Would not be able to try the fix in Jetty 10.x as currently we are on Java 8.x. Is there any plan to down merge it in Jetty 9.x? Thanks for the support. |
Jetty 9.x is now at End of Community Support. Announcement for End of Community Support for Jetty 9.x #7958 |
@prathamk this particular change has been backported to Jetty 9.4.x because the work has been sponsored by a Webtide customer that had a similar issue. However, consider moving away from Jetty 9.4.x and Java 8. Webtide can help you with the migration. |
Yeah, backlog for 2023 :) Thanks @sbordet for the update and support. |
…eDataClosedClosesStream. Regression introduced by #8678. Now using awaitility to wait for the stream count to go to zero. Signed-off-by: Simone Bordet <[email protected]>
### What changes were proposed in this pull request? This pr aims upgrade jetty to 9.4.50.v20221201 ### Why are the changes needed? This version include a bug fix: - jetty/jetty.project#8678 The release note as follows: - https://github.com/eclipse/jetty.project/releases/tag/jetty-9.4.50.v20221201 ### Does this PR introduce _any_ user-facing change? No ### How was this patch tested? Pass Github Actions Closes #39612 from LuciferYang/jetty-9-4-50. Authored-by: yangjie01 <[email protected]> Signed-off-by: Hyukjin Kwon <[email protected]>
Jetty version(s)
Jetty 9.x is now at End of Community Support
Java version/vendor
(use: java -version)
java version "1.8.0_331"
Java(TM) SE Runtime Environment (build 1.8.0_331-b09)
OS type/version
NAME="SLES"
VERSION="15-SP2"
VERSION_ID="15.2"
PRETTY_NAME="SUSE Linux Enterprise Server 15 SP2"
Description
Do not report security issues here! See Jetty Security Reports.
Jetty client is not responding to GO_AWAY packet received from (Jetty) Server and continue to send traffic on same connection.
We have observed this behavior from Jetty version 9.4.36 onwards. Our scenario is working fine on Jetty version 9.4.32. Not tested the in between versions.
Scenario:
In our scenario, we are sending the traffic via Jetty Client toward Envoy. On restart of Envoy pod, the envoy is sending the GO_AWAY frame towards client before termination. But Jetty client is not responding to the GO_AWAY frame. During the time, Jetty client is trying to send the data frames over the same connection and requests are getting failed with "IllegalStateException : session closed".
In our scenario, the Envoy again sends the GO_AWAY frame (if doesn't receive the response for the initial GO_AWAY frame) towards client after 5 sec. At that time it replies to the GO_AWAY frame. Please see below in tcp-dump screenshot.
Whereas, the same scenario with version 9.4.32, we didn't observe this behavior, its replying to GO_AWAY frame with response immediately. Please see below in tcp-dump screenshot.
Please find the Jetty client logs for when we have reproduced the issue:
How to reproduce?
Described above.
The text was updated successfully, but these errors were encountered: