Skip to content

Commit

Permalink
Merge pull request #1633 from ballerina-platform/initial-window-size
Browse files Browse the repository at this point in the history
Allow changing initial window size for client and listener
  • Loading branch information
dilanSachi authored Jun 5, 2023
2 parents 8178f30 + 560ecfa commit 954b764
Show file tree
Hide file tree
Showing 16 changed files with 74 additions and 8 deletions.
2 changes: 2 additions & 0 deletions ballerina/http_client_config.bal
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,10 @@ public type ResponseLimitConfigs record {|
# Provides settings related to HTTP/2 protocol.
#
# + http2PriorKnowledge - Configuration to enable HTTP/2 prior knowledge
# + http2InitialWindowSize - Configuration to change the initial window size
public type ClientHttp2Settings record {|
boolean http2PriorKnowledge = false;
int http2InitialWindowSize = 65535;
|};

# Provides configurations for controlling the retrying behavior in failure scenarios.
Expand Down
2 changes: 2 additions & 0 deletions ballerina/http_service_endpoint.bal
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@ public type Local record {|
# + interceptors - An array of interceptor services
# + gracefulStopTimeout - Grace period of time in seconds for listener gracefulStop
# + socketConfig - Provides settings related to server socket configuration
# + http2InitialWindowSize - Configuration to change the initial window size in HTTP/2
public type ListenerConfiguration record {|
string host = "0.0.0.0";
ListenerHttp1Settings http1Settings = {};
Expand All @@ -165,6 +166,7 @@ public type ListenerConfiguration record {|
Interceptor|Interceptor[] interceptors?;
decimal gracefulStopTimeout = DEFAULT_GRACEFULSTOP_TIMEOUT;
ServerSocketConfig socketConfig = {};
int http2InitialWindowSize = 65535;
|};

# Provides a set of cloneable configurations for HTTP listener.
Expand Down
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
- [Add runtime support for type referenced type in path parameters](https://github.com/ballerina-platform/ballerina-standard-library/issues/4372)
- [Add finite type support for query, header and path parameters](https://github.com/ballerina-platform/ballerina-standard-library/issues/4374)
- [Support for service level interceptors using `http:InterceptableService`](https://github.com/ballerina-platform/ballerina-standard-library/issues/4401)
- [Allow changing initial window size value for client and the server](https://github.com/ballerina-platform/ballerina-standard-library/issues/490)

### Changed

Expand Down
13 changes: 13 additions & 0 deletions docs/spec/spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -162,6 +162,7 @@ public type ListenerConfiguration record {|
string? server = ();
RequestLimitConfigs requestLimits = {};
Interceptor|Interceptor[] interceptors?;
int http2InitialWindowSize = 65535;
|};
```

Expand Down Expand Up @@ -1087,6 +1088,18 @@ public type ClientConfiguration record {|
ProxyConfig? proxy = ();
boolean validation = true;
|};
public type ClientHttp1Settings record {|
KeepAlive keepAlive = KEEPALIVE_AUTO;
Chunking chunking = CHUNKING_AUTO;
ProxyConfig? proxy = ();
|};
public type ClientHttp2Settings record {|
boolean http2PriorKnowledge = false;
int http2InitialWindowSize = 65535;
|};
```

Based on the config, the client object will be accompanied by following client behaviours. Following clients cannot be
Expand Down
4 changes: 4 additions & 0 deletions native/spotbugs-exclude.xml
Original file line number Diff line number Diff line change
Expand Up @@ -76,4 +76,8 @@
<Class name="io.ballerina.stdlib.http.api.HttpService$1" />
<Bug pattern="DM_EXIT" />
</Match>
<Match>
<Class name="io.ballerina.stdlib.http.api.client.endpoint.CreateSimpleHttpClient" />
<Bug pattern="REC_CATCH_EXCEPTION" />
</Match>
</FindBugsFilter>
Original file line number Diff line number Diff line change
Expand Up @@ -415,6 +415,8 @@ public class HttpConstants {
public static final BString ENDPOINT_CONFIG_VERSION = StringUtils.fromString("httpVersion");
public static final String ENDPOINT_REQUEST_LIMITS = "requestLimits";
public static final BString ENDPOINT_CONFIG_GRACEFUL_STOP_TIMEOUT = StringUtils.fromString("gracefulStopTimeout");
public static final BString ENDPOINT_CONFIG_HTTP2_INITIAL_WINDOW_SIZE = StringUtils
.fromString("http2InitialWindowSize");

public static final BString MAX_URI_LENGTH = StringUtils.fromString("maxUriLength");
public static final BString MAX_STATUS_LINE_LENGTH = StringUtils.fromString("maxStatusLineLength");
Expand Down Expand Up @@ -486,6 +488,8 @@ public class HttpConstants {
public static final BString HTTP2_SETTINGS = StringUtils.fromString("http2Settings");
public static final BString REQUEST_LIMITS = StringUtils.fromString("requestLimits");
public static final BString RESPONSE_LIMITS = StringUtils.fromString("responseLimits");
public static final BString CLIENT_EP_HTTP2_INITIAL_WINDOW_SIZE = StringUtils
.fromString("http2InitialWindowSize");

//Connection Throttling field names
public static final String CONNECTION_THROTTLING_STRUCT_REFERENCE = "connectionThrottling";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@
import static io.ballerina.runtime.observability.ObservabilityConstants.TAG_KEY_PEER_ADDRESS;
import static io.ballerina.stdlib.http.api.HttpConstants.ANN_CONFIG_ATTR_COMPRESSION_CONTENT_TYPES;
import static io.ballerina.stdlib.http.api.HttpConstants.ANN_CONFIG_ATTR_SSL_ENABLED_PROTOCOLS;
import static io.ballerina.stdlib.http.api.HttpConstants.ENDPOINT_CONFIG_HTTP2_INITIAL_WINDOW_SIZE;
import static io.ballerina.stdlib.http.api.HttpConstants.HTTP_HEADERS;
import static io.ballerina.stdlib.http.api.HttpConstants.RESOLVED_REQUESTED_URI;
import static io.ballerina.stdlib.http.api.HttpConstants.RESPONSE_CACHE_CONTROL;
Expand Down Expand Up @@ -1554,6 +1555,8 @@ public static ListenerConfiguration getListenerConfig(long port, BMap endpointCo
}

listenerConfiguration.setPipeliningEnabled(true); //Pipelining is enabled all the time
listenerConfiguration.setHttp2InitialWindowSize(endpointConfig
.getIntValue(ENDPOINT_CONFIG_HTTP2_INITIAL_WINDOW_SIZE).intValue());
return listenerConfiguration;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@
import java.net.URL;
import java.util.Map;

import static io.ballerina.stdlib.http.api.HttpConstants.CLIENT_EP_HTTP2_INITIAL_WINDOW_SIZE;
import static io.ballerina.stdlib.http.api.HttpConstants.HTTP2_PRIOR_KNOWLEDGE;
import static io.ballerina.stdlib.http.api.HttpConstants.SOCKET_CONFIG_CONNECT_TIMEOUT;
import static io.ballerina.stdlib.http.api.HttpConstants.SOCKET_CONFIG_KEEP_ALIVE;
Expand Down Expand Up @@ -100,6 +101,8 @@ public static Object createSimpleHttpClient(BObject httpClient, BMap globalPoolC
get(HttpConstants.HTTP2_SETTINGS);
boolean http2PriorKnowledge = (boolean) http2Settings.get(HTTP2_PRIOR_KNOWLEDGE);
senderConfiguration.setForceHttp2(http2PriorKnowledge);
senderConfiguration.setHttp2InitialWindowSize(http2Settings
.getIntValue(CLIENT_EP_HTTP2_INITIAL_WINDOW_SIZE).intValue());
} else {
BMap<BString, Object> http1Settings = (BMap<BString, Object>) clientEndpointConfig.get(
HttpConstants.HTTP1_SETTINGS);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,7 @@ public static ListenerConfiguration getDefault() {
private boolean tcpNoDelay;
private boolean socketReuse;
private boolean socketKeepAlive;
private int http2InitialWindowSize = 65535;

public ListenerConfiguration() {
}
Expand Down Expand Up @@ -273,4 +274,12 @@ public boolean isSocketKeepAlive() {
public void setSocketKeepAlive(boolean keepAlive) {
this.socketKeepAlive = keepAlive;
}

public int getHttp2InitialWindowSize() {
return http2InitialWindowSize;
}

public void setHttp2InitialWindowSize(int http2InitialWindowSize) {
this.http2InitialWindowSize = http2InitialWindowSize;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ public static SenderConfiguration getDefault() {
private boolean tcpNoDelay = true;
private boolean socketReuse = false;
private boolean socketKeepAlive = true;
private int http2InitialWindowSize = 65535;

public SenderConfiguration() {
this.poolConfiguration = new PoolConfiguration();
Expand Down Expand Up @@ -205,4 +206,12 @@ public boolean isSocketKeepAlive() {
public void setSocketKeepAlive(boolean socketKeepAlive) {
this.socketKeepAlive = socketKeepAlive;
}

public int getHttp2InitialWindowSize() {
return http2InitialWindowSize;
}

public void setHttp2InitialWindowSize(int http2InitialWindowSize) {
this.http2InitialWindowSize = http2InitialWindowSize;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public ServerConnector createServerConnector(ServerBootstrapConfiguration server
serverConnectorBootstrap.addIdleTimeout(listenerConfig.getSocketIdleTimeout());
if (Constants.HTTP_2_0.equals(listenerConfig.getVersion())) {
serverConnectorBootstrap.setHttp2Enabled(true);
serverConnectorBootstrap.setHttp2InitialWindowSize(listenerConfig.getHttp2InitialWindowSize());
}
serverConnectorBootstrap.addHttpTraceLogHandler(listenerConfig.isHttpTraceLogEnabled());
serverConnectorBootstrap.addHttpAccessLogHandler(listenerConfig.isHttpAccessLogEnabled());
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,6 +108,7 @@ public class HttpServerChannelInitializer extends ChannelInitializer<SocketChann
private long pipeliningLimit;
private EventExecutorGroup pipeliningGroup;
private boolean webSocketCompressionEnabled;
private int http2InitialWindowSize;

@Override
public void initChannel(SocketChannel ch) throws Exception {
Expand Down Expand Up @@ -254,7 +255,7 @@ private void configureH2cPipeline(ChannelPipeline pipeline) {
// Add handler to handle http2 requests without an upgrade
pipeline.addLast(new Http2WithPriorKnowledgeHandler(
interfaceId, serverName, serverConnectorFuture, this, allChannels, listenerChannels,
reqSizeValidationConfig.getMaxHeaderSize()));
reqSizeValidationConfig.getMaxHeaderSize(), http2InitialWindowSize));
// Add http2 upgrade decoder and upgrade handler
final HttpServerCodec sourceCodec = new HttpServerCodec(reqSizeValidationConfig.getMaxInitialLineLength(),
reqSizeValidationConfig.getMaxHeaderSize(),
Expand All @@ -276,8 +277,8 @@ private void configureH2cPipeline(ChannelPipeline pipeline) {
Constants.HTTP2_SOURCE_CONNECTION_HANDLER,
new Http2SourceConnectionHandlerBuilder(
interfaceId, serverConnectorFuture, serverName, this,
this.allChannels, this.listenerChannels,
reqSizeValidationConfig.getMaxHeaderSize()).build());
this.allChannels, this.listenerChannels, reqSizeValidationConfig.getMaxHeaderSize(),
this.http2InitialWindowSize).build());
} else {
return null;
}
Expand Down Expand Up @@ -347,6 +348,10 @@ void setReqSizeValidationConfig(InboundMsgSizeValidationConfig reqSizeValidation
this.reqSizeValidationConfig = reqSizeValidationConfig;
}

void setHttp2InitialWindowSize(int http2InitialWindowSize) {
this.http2InitialWindowSize = http2InitialWindowSize;
}

public void setChunkingConfig(ChunkConfig chunkConfig) {
this.chunkConfig = chunkConfig;
}
Expand Down Expand Up @@ -426,7 +431,8 @@ protected void configurePipeline(ChannelHandlerContext ctx, String protocol) {
Constants.HTTP2_SOURCE_CONNECTION_HANDLER,
new Http2SourceConnectionHandlerBuilder(
interfaceId, serverConnectorFuture, serverName, channelInitializer,
allChannels, listenerChannels, reqSizeValidationConfig.getMaxHeaderSize()).build());
allChannels, listenerChannels, reqSizeValidationConfig.getMaxHeaderSize(),
http2InitialWindowSize).build());
} else if (ApplicationProtocolNames.HTTP_1_1.equals(protocol)) {
// handles pipeline for HTTP/1.x requests after SSL handshake
configureHttpPipeline(ctx.pipeline(), Constants.HTTP_SCHEME);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,10 @@ public void setWebSocketCompressionEnabled(boolean webSocketCompressionEnabled)
httpServerChannelInitializer.setWebSocketCompressionEnabled(webSocketCompressionEnabled);
}

public void setHttp2InitialWindowSize(int http2InitialWindowSize) {
httpServerChannelInitializer.setHttp2InitialWindowSize(http2InitialWindowSize);
}

public ChannelGroup getListenerChannels() {
return listenerChannels;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,14 +53,16 @@ public Http2SourceConnectionHandlerBuilder(String interfaceId, ServerConnectorFu
HttpServerChannelInitializer serverChannelInitializer,
ChannelGroup allChannels,
ChannelGroup listenerChannels,
long maxHeaderListSize) {
long maxHeaderListSize,
int initialWindowSize) {
this.interfaceId = interfaceId;
this.serverConnectorFuture = serverConnectorFuture;
this.serverName = serverName;
this.serverChannelInitializer = serverChannelInitializer;
this.allChannels = allChannels;
this.listenerChannels = listenerChannels;
this.initialSettings().maxHeaderListSize(maxHeaderListSize);
this.initialSettings().initialWindowSize(initialWindowSize);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,20 +48,23 @@ public class Http2WithPriorKnowledgeHandler extends ChannelInboundHandlerAdapter
private ChannelGroup allChannels;
private ChannelGroup listenerChannels;
private long maxHeaderListSize;
private int initialWindowSize;

public Http2WithPriorKnowledgeHandler(String interfaceId, String serverName,
ServerConnectorFuture serverConnectorFuture,
HttpServerChannelInitializer serverChannelInitializer,
ChannelGroup allChannels,
ChannelGroup listenerChannels,
long maxHeaderListSize) {
long maxHeaderListSize,
int initialWindowSize) {
this.interfaceId = interfaceId;
this.serverName = serverName;
this.serverConnectorFuture = serverConnectorFuture;
this.serverChannelInitializer = serverChannelInitializer;
this.allChannels = allChannels;
this.listenerChannels = listenerChannels;
this.maxHeaderListSize = maxHeaderListSize;
this.initialWindowSize = initialWindowSize;
}

@Override
Expand All @@ -80,8 +83,7 @@ public void channelRead(ChannelHandlerContext ctx, Object msg) {
Constants.HTTP2_SOURCE_CONNECTION_HANDLER,
new Http2SourceConnectionHandlerBuilder(
interfaceId, serverConnectorFuture, serverName, serverChannelInitializer,
allChannels, listenerChannels, maxHeaderListSize).build());

allChannels, listenerChannels, maxHeaderListSize, initialWindowSize).build());
safelyRemoveHandlers(pipeline, Constants.HTTP2_UPGRADE_HANDLER,
Constants.HTTP_COMPRESSOR, Constants.HTTP_TRACE_LOG_HANDLER);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -117,6 +117,7 @@ public HttpClientChannelInitializer(SenderConfiguration senderConfiguration, Htt
if (httpTraceLogEnabled) {
connectionHandlerBuilder.frameLogger(new FrameLogger(TRACE, Constants.TRACE_LOG_UPSTREAM));
}
connectionHandlerBuilder.initialSettings().initialWindowSize(senderConfiguration.getHttp2InitialWindowSize());
http2ConnectionHandler = connectionHandlerBuilder.connection(connection).frameListener(frameListener).build();
http2TargetHandler = new Http2TargetHandler(connection, http2ConnectionHandler.encoder());
if (sslConfig != null) {
Expand Down

0 comments on commit 954b764

Please sign in to comment.