Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimone Bordet2012-07-13 12:17:35 +0000
committerSimone Bordet2012-07-13 12:17:44 +0000
commitc50e547152f7d47ac411dc7dc8c13ced334e0a82 (patch)
treee007814104aa92a08759b99712bb0f9d53077dd5 /jetty-client
parent198f713f7dd65bee34c1bb4a57fcdeaf6c2cecd4 (diff)
downloadorg.eclipse.jetty.project-c50e547152f7d47ac411dc7dc8c13ced334e0a82.tar.gz
org.eclipse.jetty.project-c50e547152f7d47ac411dc7dc8c13ced334e0a82.tar.xz
org.eclipse.jetty.project-c50e547152f7d47ac411dc7dc8c13ced334e0a82.zip
384980 - Jetty client unable to recover from Time outs when connection count per address hits max.
Test that shows that upon initial investigation, HttpClient works well, contrary to what reported in the bug.
Diffstat (limited to 'jetty-client')
-rw-r--r--jetty-client/src/test/java/org/eclipse/jetty/client/ExpirationWithLimitedConnectionsTest.java191
1 files changed, 191 insertions, 0 deletions
diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/ExpirationWithLimitedConnectionsTest.java b/jetty-client/src/test/java/org/eclipse/jetty/client/ExpirationWithLimitedConnectionsTest.java
new file mode 100644
index 0000000000..3db4a5e72b
--- /dev/null
+++ b/jetty-client/src/test/java/org/eclipse/jetty/client/ExpirationWithLimitedConnectionsTest.java
@@ -0,0 +1,191 @@
+// ========================================================================
+// Copyright 2012-2012 Mort Bay Consulting Pty. Ltd.
+// ------------------------------------------------------------------------
+// All rights reserved. This program and the accompanying materials
+// are made available under the terms of the Eclipse Public License v1.0
+// and Apache License v2.0 which accompanies this distribution.
+// The Eclipse Public License is available at
+// http://www.eclipse.org/legal/epl-v10.html
+// The Apache License v2.0 is available at
+// http://www.opensource.org/licenses/apache2.0.php
+// You may elect to redistribute this code under either of these licenses.
+// ========================================================================
+
+package org.eclipse.jetty.client;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.net.ServerSocket;
+import java.net.Socket;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.eclipse.jetty.util.log.Log;
+import org.eclipse.jetty.util.log.Logger;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class ExpirationWithLimitedConnectionsTest
+{
+ @Test
+ public void testExpirationWithMaxConnectionPerAddressReached() throws Exception
+ {
+ final Logger logger = Log.getLogger("org.eclipse.jetty.client");
+ logger.setDebugEnabled(true);
+
+ HttpClient client = new HttpClient();
+ int maxConnectionsPerAddress = 10;
+ client.setMaxConnectionsPerAddress(maxConnectionsPerAddress);
+ long timeout = 1000;
+ client.setTimeout(timeout);
+ client.start();
+
+ final List<Socket> sockets = new CopyOnWriteArrayList<Socket>();
+ final List<Exception> failures = new CopyOnWriteArrayList<Exception>();
+ final AtomicLong processingDelay = new AtomicLong(200);
+
+ final ExecutorService threadPool = Executors.newCachedThreadPool();
+ final ServerSocket server = new ServerSocket(0);
+ threadPool.submit(new Runnable()
+ {
+ public void run()
+ {
+ while (true)
+ {
+ try
+ {
+ final Socket socket = server.accept();
+ sockets.add(socket);
+ logger.debug("CONNECTION {}", socket.getRemoteSocketAddress());
+ threadPool.submit(new Runnable()
+ {
+ public void run()
+ {
+ while (true)
+ {
+ try
+ {
+ BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream(), "UTF-8"));
+ String firstLine = reader.readLine();
+ String line = firstLine;
+ while (line != null)
+ {
+ if (line.length() == 0)
+ break;
+ line = reader.readLine();
+ }
+
+ if (line == null)
+ break;
+
+ long sleep = processingDelay.get();
+ logger.debug("{} {} {} ms", firstLine, socket.getRemoteSocketAddress(), sleep);
+ TimeUnit.MILLISECONDS.sleep(sleep);
+
+ String response = "" +
+ "HTTP/1.1 200 OK\r\n" +
+ "Content-Length: 0\r\n" +
+ "\r\n";
+ OutputStream output = socket.getOutputStream();
+ output.write(response.getBytes("UTF-8"));
+ output.flush();
+ }
+ catch (Exception x)
+ {
+ failures.add(x);
+ break;
+ }
+ }
+ }
+ });
+ }
+ catch (Exception x)
+ {
+ failures.add(x);
+ break;
+ }
+ }
+ }
+ });
+
+ List<ContentExchange> exchanges = new ArrayList<ContentExchange>();
+
+ final AtomicBoolean firstExpired = new AtomicBoolean();
+ int count = 0;
+ int maxAdditionalRequest = 100;
+ int additionalRequests = 0;
+ while (true)
+ {
+ TimeUnit.MILLISECONDS.sleep(1); // Just avoid being too fast
+ ContentExchange exchange = new ContentExchange(true)
+ {
+ @Override
+ protected void onResponseComplete() throws IOException
+ {
+ logger.debug("{} {} OK", getMethod(), getRequestURI());
+ }
+
+ @Override
+ protected void onExpire()
+ {
+ logger.debug("{} {} EXPIRED {}", getMethod(), getRequestURI(), this);
+ firstExpired.compareAndSet(false, true);
+ }
+ };
+ exchanges.add(exchange);
+ Address address = new Address("localhost", server.getLocalPort());
+ exchange.setAddress(address);
+ exchange.setMethod("GET");
+ exchange.setRequestURI("/" + count);
+ exchange.setVersion("HTTP/1.1");
+ exchange.setRequestHeader("Host", address.toString());
+ logger.debug("{} {} SENT", exchange.getMethod(), exchange.getRequestURI());
+ client.send(exchange);
+ ++count;
+
+ if (processingDelay.get() > 0)
+ {
+ if (client.getDestination(address, false).getConnections() == maxConnectionsPerAddress)
+ {
+ if (firstExpired.get())
+ {
+ ++additionalRequests;
+ if (additionalRequests == maxAdditionalRequest)
+ processingDelay.set(0);
+ }
+ }
+ }
+ else
+ {
+ ++additionalRequests;
+ if (additionalRequests == 2 * maxAdditionalRequest)
+ break;
+ }
+ }
+
+ for (ContentExchange exchange : exchanges)
+ {
+ int status = exchange.waitForDone();
+ Assert.assertTrue(status == HttpExchange.STATUS_COMPLETED || status == HttpExchange.STATUS_EXPIRED);
+ }
+
+ client.stop();
+
+ Assert.assertTrue(failures.isEmpty());
+
+ for (Socket socket : sockets)
+ socket.close();
+ server.close();
+
+ threadPool.shutdown();
+ threadPool.awaitTermination(5, TimeUnit.SECONDS);
+ }
+}

Back to the top