diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java index 6dfbaa124d9..33db831e787 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpClient.java @@ -122,6 +122,7 @@ public class HttpClient extends ContainerLifeCycle private volatile SocketAddress bindAddress; private volatile long idleTimeout; private volatile boolean tcpNoDelay = true; + private volatile boolean dispatchIO = true; public HttpClient() { @@ -142,7 +143,11 @@ public class HttpClient extends ContainerLifeCycle protected void doStart() throws Exception { if (sslContextFactory != null) + { addBean(sslContextFactory); + // Avoid to double dispatch when using SSL + setDispatchIO(false); + } if (executor == null) executor = new QueuedThreadPool(); @@ -524,6 +529,32 @@ public class HttpClient extends ContainerLifeCycle this.tcpNoDelay = tcpNoDelay; } + /** + * @return true to dispatch I/O operations in a different thread, false to execute them in the selector thread + * @see #setDispatchIO(boolean) + */ + public boolean isDispatchIO() + { + return dispatchIO; + } + + /** + * Whether to dispatch I/O operations from the selector thread to a different thread. + *

+ * This implementation never blocks on I/O operation, but invokes application callbacks that may + * take time to execute or block on other I/O. + * If application callbacks are known to take time or block on I/O, then parameter {@code dispatchIO} + * must be set to true. + * If application callbacks are known to be quick and never block on I/O, then parameter {@code dispatchIO} + * may be set to false. + * + * @param dispatchIO true to dispatch I/O operations in a different thread, false to execute them in the selector thread + */ + public void setDispatchIO(boolean dispatchIO) + { + this.dispatchIO = dispatchIO; + } + @Override public void dump(Appendable out, String indent) throws IOException { diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java index bed6c6c9e02..f6f94b42159 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpConnection.java @@ -58,7 +58,7 @@ public class HttpConnection extends AbstractConnection implements Connection public HttpConnection(HttpClient client, EndPoint endPoint, HttpDestination destination) { - super(endPoint, client.getExecutor()); + super(endPoint, client.getExecutor(), client.isDispatchIO()); this.client = client; this.destination = destination; this.sender = new HttpSender(this); diff --git a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpDestination.java b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpDestination.java index b600a4d8229..b46cc75f844 100644 --- a/jetty-client/src/main/java/org/eclipse/jetty/client/HttpDestination.java +++ b/jetty-client/src/main/java/org/eclipse/jetty/client/HttpDestination.java @@ -174,7 +174,7 @@ public class HttpDestination implements Destination, AutoCloseable, Dumpable public void completed(Connection connection) { LOG.debug("Created connection {}/{} {} for {}", next, maxConnections, connection, HttpDestination.this); - process(connection, true); + process(connection, client.isDispatchIO()); } @Override diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientLoadTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientLoadTest.java index 4daeb5eae30..3056dcc5ae3 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientLoadTest.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/HttpClientLoadTest.java @@ -65,6 +65,7 @@ public class HttpClientLoadTest extends AbstractHttpClientServerTest client.setMaxConnectionsPerAddress(32768); client.setMaxQueueSizePerAddress(1024 * 1024); + client.setDispatchIO(false); Random random = new Random(); int iterations = 200;