Use GracefulShutdown when stream space is exhausted (#10946)

Motivation:

We should use GracefulShutdown when we try to create a stream and fail it because the stream space is exhausted as we may still want to process the active streams.

Modifications:

- Use graceful shutdown
- Add unit test

Result:

More graceful handling of stream creation failure due stream space exhaustation
This commit is contained in:
Norman Maurer 2021-01-16 09:55:26 +01:00 committed by GitHub
parent 342f52e813
commit 94646ac546
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 16 additions and 1 deletions

View File

@ -889,7 +889,10 @@ public class DefaultHttp2Connection implements Http2Connection {
streamId, nextStreamIdToCreate); streamId, nextStreamIdToCreate);
} }
if (nextStreamIdToCreate <= 0) { if (nextStreamIdToCreate <= 0) {
throw connectionError(REFUSED_STREAM, "Stream IDs are exhausted for this endpoint."); // We exhausted the stream id space that we can use. Let's signal this back but also signal that
// we still may want to process active streams.
throw new Http2Exception(REFUSED_STREAM, "Stream IDs are exhausted for this endpoint.",
Http2Exception.ShutdownHint.GRACEFUL_SHUTDOWN);
} }
boolean isReserved = state == RESERVED_LOCAL || state == RESERVED_REMOTE; boolean isReserved = state == RESERVED_LOCAL || state == RESERVED_REMOTE;
if (!isReserved && !canOpenStream() || isReserved && numStreams >= maxStreams) { if (!isReserved && !canOpenStream() || isReserved && numStreams >= maxStreams) {

View File

@ -370,6 +370,18 @@ public class DefaultHttp2ConnectionTest {
incrementAndGetStreamShouldRespectOverflow(client.local(), MAX_VALUE); incrementAndGetStreamShouldRespectOverflow(client.local(), MAX_VALUE);
} }
@Test
public void clientLocalCreateStreamExhaustedSpace() throws Http2Exception {
client.local().createStream(MAX_VALUE, true);
try {
client.local().createStream(MAX_VALUE, true);
fail();
} catch (Http2Exception expected) {
assertEquals(Http2Error.REFUSED_STREAM, expected.error());
assertEquals(Http2Exception.ShutdownHint.GRACEFUL_SHUTDOWN, expected.shutdownHint());
}
}
@Test(expected = Http2Exception.class) @Test(expected = Http2Exception.class)
public void newStreamBehindExpectedShouldThrow() throws Http2Exception { public void newStreamBehindExpectedShouldThrow() throws Http2Exception {
server.local().createStream(0, true); server.local().createStream(0, true);