-
Notifications
You must be signed in to change notification settings - Fork 914
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
Close a WebSocket when it is idle #5713
Conversation
🔍 Build Scan® (commit: 0b2a046) |
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 approach looks good overall 👍 Can you fix the failing test?
() -> writer.write("text"), | ||
1, TimeUnit.SECONDS | ||
); | ||
Thread.sleep(Duration.ofSeconds(10).toMillis()); |
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; we probably don't want a 10 second test since it will slow down our build.
@Test | ||
void shouldThrowWhenWritingToIdleWebSocket() throws Exception { | ||
final Throwable ex = assertThrows(RuntimeException.class, () -> { | ||
final WebSocketClient client = WebSocketClient.of(SessionProtocol.H1C, server.httpEndpoint()); |
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.
@ikhoon Did you imagine that only HTTP1 needs this kind of behavior when creating the issue? I'm curious if we don't need to consider H2C as well.
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.
- Thank you for your quick review.
- In case of a failed test, it may be a little late because I'm in the military. But I'll fix it ASAP.
- Below is a summary of why I didn't consider H2C, and what I understood about the WebSocket code.
- Please let me know if there's anything wrong.
Reason
-
In HTTP2 protocol, close the idle channel by the
AbstractKeepAliveHandler
class, the parent of theHTTP2ServerKeepAliveHandler
generated by theHTTP2ServerConnectionHandler
-
HTTP2 idleTimeout features already tested in
KeepAliveHandlerTest
-
I modified, the
WebSocketServiceChannelHandler
, is registered in Channel Pipelineonly for HTTP1 protocol
-
AbstractKeepAliveHandler
was usingidleTimeoutMillis
inServerConfig
to close the idle channel,WebSocketServiceChannelHandler
also usesidleTimeoutMillis
inServerConfig
for the same result
About Web Socket Operation
HTTP/2(H2C)
- When connected by
SessionProtocol.H2C
, theHttp2ServerConnectionHandler
is registered in the channel pipeline as shown in the picture.
- When the
Http2ServerConnectionHandler
is created, if theidleTimeoutMillis
is not0
, create theHttp2ServerKeepAliveHandler
as shown in the picture below.
- In
AbstractKeepAliveHandler
, parent of theHttp2ServerKeepAliveHandler
, close the idle channel like the log below.
16:20:27.830 [armeria-common-worker-nio-3-2] DEBUG c.l.a.i.c.AbstractKeepAliveHandler - [id: 0x0af5558b, L:/127.0.0.1:55809 - R:/127.0.0.1:55811] Closing an idle server connection
HTTP/1(H1C)
- When you connect to
SessionProtocol.H1C
, decode the request in theHttp1RequestDecoder
.
- If the request is WebSocketUpgradeRequest, replace the
Http1RequestDecoder
with theWebSocketServiceChannelHandler
as shown in the picture below.
-
However, there was no idleTimeout-related code in the existing WebSocketServiceChannelHandler
-
So when connected with the HTTP1 protocol, the channel did not close if the idle state continued.
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 HTTP2 protocol, close the idle channel by the AbstractKeepAliveHandler class, the parent of the HTTP2ServerKeepAliveHandler generated by the HTTP2ServerConnectionHandler
Sure, but I thought Http2ServerKeepAliveHandler
also operated on the connection level. I was asking the original issue creator because I was looking at the following line which seemed to imply an idle timeout for requests which h2c doesn't have at the moment.
The existing idle timeout handler operates at the connection level so a new scheduler that can perform at the WebSocket level is necessary.
What do you think about solving this issue in a more generic way? We could add idle timeout settings to any
|
Related: #5696
Motivation:
Modifications:
new WebSocketServiceChannelHandler()
Parameter inpipeline.replace()
Result: