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:
nmittler 2015-05-13 09:50:32 -07:00
parent 8bc992091c
commit 5efbb6fe73
2 changed files with 23 additions and 31 deletions

View File

@ -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();
} }

View File

@ -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