Fix a bug where closing a websocket session could send a RST_STREAM frame - #6375
Merged
Conversation
Codecov Report❌ Patch coverage is Additional details and impacted files@@ Coverage Diff @@
## main #6375 +/- ##
============================================
- Coverage 74.46% 74.09% -0.37%
- Complexity 22234 22984 +750
============================================
Files 1963 2061 +98
Lines 82437 86105 +3668
Branches 10764 11306 +542
============================================
+ Hits 61385 63802 +2417
- Misses 15918 16893 +975
- Partials 5134 5410 +276 ☔ View full report in Codecov by Sentry. 🚀 New features to boost your workflow:
|
Contributor
jrhee17
force-pushed
the
bugfix/websocket-rst
branch
from
August 28, 2025 10:07
1b73e7f to
9cdd41d
Compare
jrhee17
marked this pull request as ready for review
August 29, 2025 01:00
ikhoon
reviewed
Sep 1, 2025
minwoox
approved these changes
Sep 2, 2025
| .requestTimeoutMillis(WebSocketUtil.DEFAULT_REQUEST_RESPONSE_TIMEOUT_MILLIS) | ||
| .maxRequestLength(WebSocketUtil.DEFAULT_MAX_REQUEST_RESPONSE_LENGTH) | ||
| .requestAutoAbortDelayMillis(WebSocketUtil.DEFAULT_REQUEST_AUTO_ABORT_DELAY_MILLIS) | ||
| .closeHttp2StreamDelayMillis(10_000) // follows netty's forceCloseTimeoutMillis default |
Contributor
There was a problem hiding this comment.
Could you put this value in WebSocketUtil?
Could you update the Javadoc?
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Motivation:
Currently, once an
HttpRequestandHttpResponseis completed, the underlying HTTP2 stream is cancelled using aRST_STREAM.This makes sense for normal HTTP constructs since it indicates that we are no longer interested in the request, and we would like to release resources associated with it.
However, some protocols such as WebSockets implement their own graceful shutdown procedure.
In detail, Armeria's
HttpRequest,HttpResponseimplements WebSocket graceful shutdown and the reactive stream implementation is closed when aCLOSEframe is both sent and received.However, although the websocket session is completed, the underlying HTTP2 stream may not necessarily be complete.
Protocol-wise, there is an inherent discrepancy between websocket session completion and HTTP2 stream completion.
The current implementation defaults to sending a
RST_STREAMimmediately once the correspondingHttpRequestandHttpResponse. For websockets, I propose that a delay is given so that the remote has a chance to end the stream.Assuming that we will tie the lifecycle of inbound
WebSockets with outboundWebSockets (so sending a close frame also closes the inbound) in #6357 , this option can be thought of similar to netty'sforceCloseTimeoutMillisoption. (which acts as a timeout since sending the CLOSE frame)Modifications:
closeHttp2StreamDelayMillisoption toServiceConfigand relevant implementationsWebSocketServicesets acloseHttp2StreamDelayMillisof 10 seconds by defaultHttpServerHandlerdecides when to send aRST_STREAMbased on thecloseHttp2StreamDelayMillisHttp2StreamLifecycleHandlerwhich maintains the lifecycle of reset futures. This ensures that scheduled futures aren't leaked for servers with high throughput.maybeResetStreamis called.notifyStreamClosedis called to clean up possibly scheduled futures.Result:
RST_STREAMframe