Skip to content
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

HTTP client improvements #4825

Closed
wants to merge 8 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
44 changes: 35 additions & 9 deletions src/main/asciidoc/http.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -805,7 +805,7 @@ You can configure compressors according to your needs

=== Creating an HTTP client

You create an {@link io.vertx.core.http.HttpClient} instance with default options as follows:
Youu create an {@link io.vertx.core.http.HttpClientPool} instance with default options as follows:

[source,$lang]
----
Expand Down Expand Up @@ -850,6 +850,26 @@ When a clients connects to an HTTP/2 server, it sends to the server its {@link i
The settings define how the server can use the connection, the default initial settings for a client are the default
values defined by the HTTP/2 RFC.

=== Pool configuration

For performance purpose, the client uses connection pooling when interacting with HTTP/1.1 servers. The pool creates up
to 5 connections per server. You can override the pool configuration like this:

[source,$lang]
----
{@link examples.HTTPExamples#examplePoolConfiguration}
----

You can configure various pool {@link io.vertx.core.http.PoolOptions options} as follows

- {@link io.vertx.core.http.PoolOptions options#setHttp1MaxSize} the maximum number of opened per HTTP/1.x server (5 by default)
- {@link io.vertx.core.http.PoolOptions options#setHttp2MaxSize} the maximum number of opened per HTTP/2 server (1 by default), you *should* not change this value since a single HTTP/2 connection is capable of delivering the same performance level than multiple HTTP/1.x connections
- {@link io.vertx.core.http.PoolOptions options#setCleanerPeriod} the period in milliseconds at which the pool checks expired connections (1 second by default)
- {@link io.vertx.core.http.PoolOptions options#setEventLoopSize} sets the number of event loops the pool use (0 by default)
- a value of 0 configures the pool to use the event loop of the caller
- a positive value configures the pool load balance the creation of connection over a list of event loops determined by the value
- {@link io.vertx.core.http.PoolOptions options#setMaxWaitQueueSize} the maximum number of HTTP requests waiting until a connection is available, when the queue is full, the request is rejected

=== Logging network client activity

For debugging purposes, network activity can be logged.
Expand Down Expand Up @@ -1413,7 +1433,7 @@ When keep alive is enabled. Vert.x will add a `Connection: Keep-Alive` header to
When keep alive is disabled. Vert.x will add a `Connection: Close` header to each HTTP/1.1 request sent to signal
that the connection will be closed after completion of the response.

The maximum number of connections to pool *for each server* is configured using {@link io.vertx.core.http.HttpClientOptions#setMaxPoolSize(int)}
The maximum number of connections to pool *for each server* is configured using {@link io.vertx.core.http.PoolOptions#setHttp1MaxSize(int)}

When making a request with pooling enabled, Vert.x will create a new connection if there are less than the maximum number of
connections already created for that server, otherwise it will add the request to a queue.
Expand Down Expand Up @@ -1449,7 +1469,7 @@ fairness of the distribution of the client requests over the connections to the
HTTP/2 advocates to use a single connection to a server, by default the http client uses a single
connection for each server, all the streams to the same server are multiplexed over the same connection.

When the clients needs to use more than a single connection and use pooling, the {@link io.vertx.core.http.HttpClientOptions#setHttp2MaxPoolSize(int)}
When the clients needs to use more than a single connection and use pooling, the {@link io.vertx.core.http.PoolOptions#setHttp2MaxSize(int)}
shall be used.

When it is desirable to limit the number of multiplexed streams per connection and use a connection
Expand Down Expand Up @@ -1798,18 +1818,24 @@ The {@link io.vertx.core.http.ServerWebSocket} instance enables you to retrieve

==== WebSockets on the client

The Vert.x {@link io.vertx.core.http.HttpClient} supports WebSockets.

You can connect a WebSocket to a server using one of the {@link io.vertx.core.http.HttpClient#webSocket} operations and
providing a handler.
e Vert.x {@link io.vertx.core.http.WebSocketClient} supports WebSockets.

The handler will be called with an instance of {@link io.vertx.core.http.WebSocket} when the connection has been made:
You can connect a WebSocket to a server using one of the {@link io.vertx.core.http.WebSocketClient#connect} operations.

The returned future will be completed with an instance of {@link io.vertx.core.http.WebSocket} when the connection has been made:
[source,$lang]
----
{@link examples.HTTPExamples#example54}
----

en connecting from a non Vert.x thread, you can create a {@link io.vertx.core.http.ClientWebSocket}, configure its handlers and
then connect to the server:

[source,$lang]
----
{@link examples.HTTPExamples#example54_bis}
----

By default, the client sets the `origin` header to the server host, e.g http://www.example.com. Some servers will refuse
such request, you can configure the client to not set this header.

Expand Down Expand Up @@ -1839,7 +1865,7 @@ If you wish to write a single WebSocket message to the WebSocket you can do this
----

If the WebSocket message is larger than the maximum WebSocket frame size as configured with
{@link io.vertx.core.http.HttpClientOptions#setMaxWebSocketFrameSize(int)}
{@link io.vertx.core.http.WebSocketClientOptions#setMaxFrameSize(int)}
then Vert.x will split it into multiple WebSocket frames before sending it on the wire.

==== Writing frames to WebSockets
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,11 +70,6 @@ static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, HttpCli
obj.setHttp2KeepAliveTimeout(((Number)member.getValue()).intValue());
}
break;
case "http2MaxPoolSize":
if (member.getValue() instanceof Number) {
obj.setHttp2MaxPoolSize(((Number)member.getValue()).intValue());
}
break;
case "http2MultiplexingLimit":
if (member.getValue() instanceof Number) {
obj.setHttp2MultiplexingLimit(((Number)member.getValue()).intValue());
Expand Down Expand Up @@ -110,36 +105,11 @@ static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, HttpCli
obj.setMaxInitialLineLength(((Number)member.getValue()).intValue());
}
break;
case "maxPoolSize":
if (member.getValue() instanceof Number) {
obj.setMaxPoolSize(((Number)member.getValue()).intValue());
}
break;
case "maxRedirects":
if (member.getValue() instanceof Number) {
obj.setMaxRedirects(((Number)member.getValue()).intValue());
}
break;
case "maxWaitQueueSize":
if (member.getValue() instanceof Number) {
obj.setMaxWaitQueueSize(((Number)member.getValue()).intValue());
}
break;
case "maxWebSocketFrameSize":
if (member.getValue() instanceof Number) {
obj.setMaxWebSocketFrameSize(((Number)member.getValue()).intValue());
}
break;
case "maxWebSocketMessageSize":
if (member.getValue() instanceof Number) {
obj.setMaxWebSocketMessageSize(((Number)member.getValue()).intValue());
}
break;
case "maxWebSockets":
if (member.getValue() instanceof Number) {
obj.setMaxWebSockets(((Number)member.getValue()).intValue());
}
break;
case "name":
if (member.getValue() instanceof String) {
obj.setName((String)member.getValue());
Expand All @@ -155,26 +125,11 @@ static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, HttpCli
obj.setPipeliningLimit(((Number)member.getValue()).intValue());
}
break;
case "poolCleanerPeriod":
if (member.getValue() instanceof Number) {
obj.setPoolCleanerPeriod(((Number)member.getValue()).intValue());
}
break;
case "poolEventLoopSize":
if (member.getValue() instanceof Number) {
obj.setPoolEventLoopSize(((Number)member.getValue()).intValue());
}
break;
case "protocolVersion":
if (member.getValue() instanceof String) {
obj.setProtocolVersion(io.vertx.core.http.HttpVersion.valueOf((String)member.getValue()));
}
break;
case "sendUnmaskedFrames":
if (member.getValue() instanceof Boolean) {
obj.setSendUnmaskedFrames((Boolean)member.getValue());
}
break;
case "shared":
if (member.getValue() instanceof Boolean) {
obj.setShared((Boolean)member.getValue());
Expand All @@ -190,43 +145,11 @@ static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, HttpCli
obj.setTryUseCompression((Boolean)member.getValue());
}
break;
case "tryUsePerFrameWebSocketCompression":
if (member.getValue() instanceof Boolean) {
obj.setTryUsePerFrameWebSocketCompression((Boolean)member.getValue());
}
break;
case "tryUsePerMessageWebSocketCompression":
if (member.getValue() instanceof Boolean) {
obj.setTryUsePerMessageWebSocketCompression((Boolean)member.getValue());
}
break;
case "tryWebSocketDeflateFrameCompression":
break;
case "verifyHost":
if (member.getValue() instanceof Boolean) {
obj.setVerifyHost((Boolean)member.getValue());
}
break;
case "webSocketClosingTimeout":
if (member.getValue() instanceof Number) {
obj.setWebSocketClosingTimeout(((Number)member.getValue()).intValue());
}
break;
case "webSocketCompressionAllowClientNoContext":
if (member.getValue() instanceof Boolean) {
obj.setWebSocketCompressionAllowClientNoContext((Boolean)member.getValue());
}
break;
case "webSocketCompressionLevel":
if (member.getValue() instanceof Number) {
obj.setWebSocketCompressionLevel(((Number)member.getValue()).intValue());
}
break;
case "webSocketCompressionRequestServerNoContext":
if (member.getValue() instanceof Boolean) {
obj.setWebSocketCompressionRequestServerNoContext((Boolean)member.getValue());
}
break;
}
}
}
Expand All @@ -251,7 +174,6 @@ static void toJson(HttpClientOptions obj, java.util.Map<String, Object> json) {
json.put("http2ClearTextUpgradeWithPreflightRequest", obj.isHttp2ClearTextUpgradeWithPreflightRequest());
json.put("http2ConnectionWindowSize", obj.getHttp2ConnectionWindowSize());
json.put("http2KeepAliveTimeout", obj.getHttp2KeepAliveTimeout());
json.put("http2MaxPoolSize", obj.getHttp2MaxPoolSize());
json.put("http2MultiplexingLimit", obj.getHttp2MultiplexingLimit());
if (obj.getInitialSettings() != null) {
json.put("initialSettings", obj.getInitialSettings().toJson());
Expand All @@ -261,34 +183,20 @@ static void toJson(HttpClientOptions obj, java.util.Map<String, Object> json) {
json.put("maxChunkSize", obj.getMaxChunkSize());
json.put("maxHeaderSize", obj.getMaxHeaderSize());
json.put("maxInitialLineLength", obj.getMaxInitialLineLength());
json.put("maxPoolSize", obj.getMaxPoolSize());
json.put("maxRedirects", obj.getMaxRedirects());
json.put("maxWaitQueueSize", obj.getMaxWaitQueueSize());
json.put("maxWebSocketFrameSize", obj.getMaxWebSocketFrameSize());
json.put("maxWebSocketMessageSize", obj.getMaxWebSocketMessageSize());
json.put("maxWebSockets", obj.getMaxWebSockets());
if (obj.getName() != null) {
json.put("name", obj.getName());
}
json.put("pipelining", obj.isPipelining());
json.put("pipeliningLimit", obj.getPipeliningLimit());
json.put("poolCleanerPeriod", obj.getPoolCleanerPeriod());
json.put("poolEventLoopSize", obj.getPoolEventLoopSize());
if (obj.getProtocolVersion() != null) {
json.put("protocolVersion", obj.getProtocolVersion().name());
}
json.put("sendUnmaskedFrames", obj.isSendUnmaskedFrames());
json.put("shared", obj.isShared());
if (obj.getTracingPolicy() != null) {
json.put("tracingPolicy", obj.getTracingPolicy().name());
}
json.put("tryUseCompression", obj.isTryUseCompression());
json.put("tryUsePerMessageWebSocketCompression", obj.getTryUsePerMessageWebSocketCompression());
json.put("tryWebSocketDeflateFrameCompression", obj.getTryWebSocketDeflateFrameCompression());
json.put("verifyHost", obj.isVerifyHost());
json.put("webSocketClosingTimeout", obj.getWebSocketClosingTimeout());
json.put("webSocketCompressionAllowClientNoContext", obj.getWebSocketCompressionAllowClientNoContext());
json.put("webSocketCompressionLevel", obj.getWebSocketCompressionLevel());
json.put("webSocketCompressionRequestServerNoContext", obj.getWebSocketCompressionRequestServerNoContext());
}
}
63 changes: 63 additions & 0 deletions src/main/generated/io/vertx/core/http/PoolOptionsConverter.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
package io.vertx.core.http;

import io.vertx.core.json.JsonObject;
import io.vertx.core.json.JsonArray;
import io.vertx.core.json.impl.JsonUtil;
import java.time.Instant;
import java.time.format.DateTimeFormatter;
import java.util.Base64;

/**
* Converter and mapper for {@link io.vertx.core.http.PoolOptions}.
* NOTE: This class has been automatically generated from the {@link io.vertx.core.http.PoolOptions} original class using Vert.x codegen.
*/
public class PoolOptionsConverter {


private static final Base64.Decoder BASE64_DECODER = JsonUtil.BASE64_DECODER;
private static final Base64.Encoder BASE64_ENCODER = JsonUtil.BASE64_ENCODER;

static void fromJson(Iterable<java.util.Map.Entry<String, Object>> json, PoolOptions obj) {
for (java.util.Map.Entry<String, Object> member : json) {
switch (member.getKey()) {
case "cleanerPeriod":
if (member.getValue() instanceof Number) {
obj.setCleanerPeriod(((Number)member.getValue()).intValue());
}
break;
case "eventLoopSize":
if (member.getValue() instanceof Number) {
obj.setEventLoopSize(((Number)member.getValue()).intValue());
}
break;
case "http1MaxSize":
if (member.getValue() instanceof Number) {
obj.setHttp1MaxSize(((Number)member.getValue()).intValue());
}
break;
case "http2MaxSize":
if (member.getValue() instanceof Number) {
obj.setHttp2MaxSize(((Number)member.getValue()).intValue());
}
break;
case "maxWaitQueueSize":
if (member.getValue() instanceof Number) {
obj.setMaxWaitQueueSize(((Number)member.getValue()).intValue());
}
break;
}
}
}

static void toJson(PoolOptions obj, JsonObject json) {
toJson(obj, json.getMap());
}

static void toJson(PoolOptions obj, java.util.Map<String, Object> json) {
json.put("cleanerPeriod", obj.getCleanerPeriod());
json.put("eventLoopSize", obj.getEventLoopSize());
json.put("http1MaxSize", obj.getHttp1MaxSize());
json.put("http2MaxSize", obj.getHttp2MaxSize());
json.put("maxWaitQueueSize", obj.getMaxWaitQueueSize());
}
}
Loading
Loading