-
Notifications
You must be signed in to change notification settings - Fork 914
Make the initial window size for H2 configurable #1551
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
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"type": "feature", | ||
"category": "Netty NIO HTTP Client", | ||
"description": "`SETTINGS_INITIAL_WINDOW_SIZE` is now configurable on HTTP/2 connections opened by the Netty client using `Http2Configuration#initialWindowSize(Integer)` along with `NettyNioAsyncHttpClient.Builder#http2Configuration(Http2Configuration)`. See https://tools.ietf.org/html/rfc7540#section-6.5.2 for more information." | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,148 @@ | ||
/* | ||
* Copyright 2010-2019 Amazon.com, Inc. or its affiliates. All Rights Reserved. | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"). | ||
* You may not use this file except in compliance with the License. | ||
* A copy of the License is located at | ||
* | ||
* http://aws.amazon.com/apache2.0 | ||
* | ||
* or in the "license" file accompanying this file. This file is distributed | ||
* on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either | ||
* express or implied. See the License for the specific language governing | ||
* permissions and limitations under the License. | ||
*/ | ||
|
||
package software.amazon.awssdk.http.nio.netty; | ||
|
||
import software.amazon.awssdk.annotations.SdkPublicApi; | ||
import software.amazon.awssdk.utils.Validate; | ||
import software.amazon.awssdk.utils.builder.CopyableBuilder; | ||
import software.amazon.awssdk.utils.builder.ToCopyableBuilder; | ||
|
||
/** | ||
* Configuration specific to HTTP/2 connections. | ||
*/ | ||
@SdkPublicApi | ||
public final class Http2Configuration implements ToCopyableBuilder<Http2Configuration.Builder, Http2Configuration> { | ||
private final Long maxStreams; | ||
private final Integer initialWindowSize; | ||
|
||
private Http2Configuration(DefaultBuilder builder) { | ||
this.maxStreams = builder.maxStreams; | ||
this.initialWindowSize = builder.initialWindowSize; | ||
} | ||
|
||
/** | ||
* @return The maximum number of streams to be created per HTTP/2 connection. | ||
*/ | ||
public Long maxStreams() { | ||
return maxStreams; | ||
} | ||
|
||
/** | ||
* @return The initial window size for an HTTP/2 stream. | ||
*/ | ||
public Integer initialWindowSize() { | ||
return initialWindowSize; | ||
} | ||
|
||
@Override | ||
public Builder toBuilder() { | ||
return new DefaultBuilder(this); | ||
} | ||
|
||
@Override | ||
public boolean equals(Object o) { | ||
if (this == o) { | ||
return true; | ||
} | ||
|
||
if (o == null || getClass() != o.getClass()) { | ||
return false; | ||
} | ||
|
||
Http2Configuration that = (Http2Configuration) o; | ||
|
||
if (maxStreams != null ? !maxStreams.equals(that.maxStreams) : that.maxStreams != null) { | ||
return false; | ||
} | ||
|
||
return initialWindowSize != null ? initialWindowSize.equals(that.initialWindowSize) : that.initialWindowSize == null; | ||
|
||
} | ||
|
||
@Override | ||
public int hashCode() { | ||
int result = maxStreams != null ? maxStreams.hashCode() : 0; | ||
result = 31 * result + (initialWindowSize != null ? initialWindowSize.hashCode() : 0); | ||
return result; | ||
} | ||
|
||
public static Builder builder() { | ||
return new DefaultBuilder(); | ||
} | ||
|
||
public interface Builder extends CopyableBuilder<Builder, Http2Configuration> { | ||
|
||
/** | ||
* Sets the max number of concurrent streams per connection. | ||
* | ||
* <p>Note that this cannot exceed the value of the MAX_CONCURRENT_STREAMS setting returned by the service. If it | ||
* does the service setting is used instead.</p> | ||
* | ||
* @param maxStreams Max concurrent HTTP/2 streams per connection. | ||
* @return This builder for method chaining. | ||
*/ | ||
Builder maxStreams(Long maxStreams); | ||
|
||
/** | ||
* Sets initial window size of a stream. This setting is only respected when the HTTP/2 protocol is used. | ||
* | ||
* See <a href="https://tools.ietf.org/html/rfc7540#section-6.5.2">https://tools.ietf.org/html/rfc7540#section-6.5.2</a> | ||
* for more information about this parameter. | ||
* | ||
* @param initialWindowSize The initial window size of a stream. | ||
* @return This builder for method chaining. | ||
*/ | ||
Builder initialWindowSize(Integer initialWindowSize); | ||
} | ||
|
||
private static final class DefaultBuilder implements Builder { | ||
private Long maxStreams; | ||
private Integer initialWindowSize; | ||
|
||
private DefaultBuilder() { | ||
} | ||
|
||
private DefaultBuilder(Http2Configuration http2Configuration) { | ||
this.maxStreams = http2Configuration.maxStreams; | ||
this.initialWindowSize = http2Configuration.initialWindowSize; | ||
} | ||
|
||
@Override | ||
public Builder maxStreams(Long maxStreams) { | ||
this.maxStreams = Validate.isPositiveOrNull(maxStreams, "maxStreams"); | ||
return this; | ||
} | ||
|
||
public void setMaxStreams(Long maxStreams) { | ||
maxStreams(maxStreams); | ||
} | ||
|
||
@Override | ||
public Builder initialWindowSize(Integer initialWindowSize) { | ||
this.initialWindowSize = Validate.isPositiveOrNull(initialWindowSize, "initialWindowSize"); | ||
return this; | ||
} | ||
|
||
public void setInitialWindowSize(Integer initialWindowSize) { | ||
initialWindowSize(initialWindowSize); | ||
} | ||
|
||
@Override | ||
public Http2Configuration build() { | ||
return new Http2Configuration(this); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -53,19 +53,22 @@ public final class ChannelPipelineInitializer extends AbstractChannelPoolHandler | |
private final Protocol protocol; | ||
private final SslContext sslCtx; | ||
private final long clientMaxStreams; | ||
private final int clientInitialWindowSize; | ||
private final AtomicReference<ChannelPool> channelPoolRef; | ||
private final NettyConfiguration configuration; | ||
private final URI poolKey; | ||
|
||
public ChannelPipelineInitializer(Protocol protocol, | ||
SslContext sslCtx, | ||
long clientMaxStreams, | ||
int clientInitialWindowSize, | ||
AtomicReference<ChannelPool> channelPoolRef, | ||
NettyConfiguration configuration, | ||
URI poolKey) { | ||
this.protocol = protocol; | ||
this.sslCtx = sslCtx; | ||
this.clientMaxStreams = clientMaxStreams; | ||
this.clientInitialWindowSize = clientInitialWindowSize; | ||
this.channelPoolRef = channelPoolRef; | ||
this.configuration = configuration; | ||
this.poolKey = poolKey; | ||
|
@@ -125,7 +128,7 @@ private void configureHttp2(Channel ch, ChannelPipeline pipeline) { | |
Http2FrameCodec codec = | ||
Http2FrameCodecBuilder.forClient() | ||
.headerSensitivityDetector((name, value) -> lowerCase(name.toString()).equals("authorization")) | ||
.initialSettings(Http2Settings.defaultSettings().initialWindowSize(1_048_576)) | ||
.initialSettings(Http2Settings.defaultSettings().initialWindowSize(clientInitialWindowSize)) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Hi @dagnir , I am doing a netty http2 based project by referencing aws sdk netty implementation. However, my frame size is limited to 64KB even if I change initial window size to 1MB(both server and client), set max frame size to 1MB and netty buffer size to 1MB. Do you have any suggestion for this case? Do I need to have a settingFrameHandler? (I thought Netty http2 automatically process it.) Here is a sample output of sending 1MB data from client to server.
|
||
.frameLogger(new Http2FrameLogger(LogLevel.DEBUG)) | ||
.build(); | ||
|
||
|
Uh oh!
There was an error while loading. Please reload this page.