mirror of https://github.com/grpc/grpc-java.git
Allow 100 streams initially rather than 10.
The HTTP/2 spec suggests 100 as the recommended minimum for SETTINGS_MAX_CONCURRENT_STREAMS (https://tools.ietf.org/html/draft-ietf-httpbis-http2-17#section-6.5.2). We should use this value as our default.
This commit is contained in:
parent
8bc992091c
commit
5efbb6fe73
|
|
@ -68,10 +68,10 @@ import java.util.TreeMap;
|
||||||
*/
|
*/
|
||||||
class BufferingHttp2ConnectionEncoder extends DecoratingHttp2ConnectionEncoder {
|
class BufferingHttp2ConnectionEncoder extends DecoratingHttp2ConnectionEncoder {
|
||||||
/**
|
/**
|
||||||
* The number of new streams we allow to be created before receiving the first {@code SETTINGS}
|
* The assumed minimum value for {@code SETTINGS_MAX_CONCURRENT_STREAMS} as
|
||||||
* frame from the server.
|
* recommended by the HTTP/2 spec.
|
||||||
*/
|
*/
|
||||||
private static final int NUM_STREAMS_INITIALLY_ALLOWED = 10;
|
static final int SMALLEST_MAX_CONCURRENT_STREAMS = 100;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Buffer for any streams and corresponding frames that could not be created
|
* Buffer for any streams and corresponding frames that could not be created
|
||||||
|
|
@ -79,12 +79,19 @@ class BufferingHttp2ConnectionEncoder extends DecoratingHttp2ConnectionEncoder {
|
||||||
*/
|
*/
|
||||||
private final TreeMap<Integer, PendingStream> pendingStreams =
|
private final TreeMap<Integer, PendingStream> pendingStreams =
|
||||||
new TreeMap<Integer, PendingStream>();
|
new TreeMap<Integer, PendingStream>();
|
||||||
|
private final int initialMaxConcurrentStreams;
|
||||||
// Smallest stream id whose corresponding frames do not get buffered.
|
// Smallest stream id whose corresponding frames do not get buffered.
|
||||||
private int largestCreatedStreamId;
|
private int largestCreatedStreamId;
|
||||||
private boolean receivedSettings;
|
private boolean receivedSettings;
|
||||||
|
|
||||||
protected BufferingHttp2ConnectionEncoder(Http2ConnectionEncoder delegate) {
|
protected BufferingHttp2ConnectionEncoder(Http2ConnectionEncoder delegate) {
|
||||||
|
this(delegate, SMALLEST_MAX_CONCURRENT_STREAMS);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected BufferingHttp2ConnectionEncoder(Http2ConnectionEncoder delegate,
|
||||||
|
int initialMaxConcurrentStreams) {
|
||||||
super(delegate);
|
super(delegate);
|
||||||
|
this.initialMaxConcurrentStreams = initialMaxConcurrentStreams;
|
||||||
connection().addListener(new Http2ConnectionAdapter() {
|
connection().addListener(new Http2ConnectionAdapter() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
@ -225,7 +232,7 @@ class BufferingHttp2ConnectionEncoder extends DecoratingHttp2ConnectionEncoder {
|
||||||
*/
|
*/
|
||||||
private boolean canCreateStream() {
|
private boolean canCreateStream() {
|
||||||
Http2Connection.Endpoint<?> local = connection().local();
|
Http2Connection.Endpoint<?> local = connection().local();
|
||||||
return (receivedSettings || local.numActiveStreams() < NUM_STREAMS_INITIALLY_ALLOWED)
|
return (receivedSettings || local.numActiveStreams() < initialMaxConcurrentStreams)
|
||||||
&& local.canCreateStream();
|
&& local.canCreateStream();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -344,38 +344,23 @@ public class BufferingHttp2ConnectionEncoderTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void bufferUntilSettingsReceived() {
|
public void bufferUntilSettingsReceived() {
|
||||||
encoderWriteHeaders(3, promise);
|
int initialLimit = BufferingHttp2ConnectionEncoder.SMALLEST_MAX_CONCURRENT_STREAMS;
|
||||||
encoderWriteHeaders(5, promise);
|
int numStreams = initialLimit * 2;
|
||||||
encoderWriteHeaders(7, promise);
|
for (int ix = 0, nextStreamId = 3; ix < numStreams; ++ix, nextStreamId += 2) {
|
||||||
encoderWriteHeaders(9, promise);
|
encoderWriteHeaders(nextStreamId, promise);
|
||||||
encoderWriteHeaders(11, promise);
|
if (ix < initialLimit) {
|
||||||
encoderWriteHeaders(13, promise);
|
writeVerifyWriteHeaders(times(1), nextStreamId, promise);
|
||||||
encoderWriteHeaders(15, promise);
|
} else {
|
||||||
encoderWriteHeaders(17, promise);
|
writeVerifyWriteHeaders(never(), nextStreamId, promise);
|
||||||
encoderWriteHeaders(19, promise);
|
}
|
||||||
encoderWriteHeaders(21, promise);
|
}
|
||||||
encoderWriteHeaders(23, promise);
|
assertEquals(numStreams / 2, encoder.numBufferedStreams());
|
||||||
assertEquals(1, encoder.numBufferedStreams());
|
|
||||||
|
|
||||||
writeVerifyWriteHeaders(times(1), 3, promise);
|
|
||||||
writeVerifyWriteHeaders(times(1), 5, promise);
|
|
||||||
writeVerifyWriteHeaders(times(1), 7, promise);
|
|
||||||
writeVerifyWriteHeaders(times(1), 9, promise);
|
|
||||||
writeVerifyWriteHeaders(times(1), 11, promise);
|
|
||||||
writeVerifyWriteHeaders(times(1), 13, promise);
|
|
||||||
writeVerifyWriteHeaders(times(1), 15, promise);
|
|
||||||
writeVerifyWriteHeaders(times(1), 17, promise);
|
|
||||||
writeVerifyWriteHeaders(times(1), 19, promise);
|
|
||||||
writeVerifyWriteHeaders(times(1), 21, promise);
|
|
||||||
writeVerifyWriteHeaders(never(), 23, promise);
|
|
||||||
|
|
||||||
// Simulate that we received a SETTINGS frame.
|
// Simulate that we received a SETTINGS frame.
|
||||||
encoder.writeSettingsAck(ctx, promise);
|
encoder.writeSettingsAck(ctx, promise);
|
||||||
|
|
||||||
assertEquals(0, encoder.numBufferedStreams());
|
assertEquals(0, encoder.numBufferedStreams());
|
||||||
writeVerifyWriteHeaders(times(1), 23, promise);
|
assertEquals(numStreams, connection.local().numActiveStreams());
|
||||||
|
|
||||||
assertEquals(11, connection.local().numActiveStreams());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue