From e48570bd5e35f1bc86cee549e44535f3eb5319fc Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 17 Nov 2011 07:14:40 +1100 Subject: [PATCH 1/5] SSL progress measured by process not inbound --- .../java/org/eclipse/jetty/io/nio/SslConnection.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslConnection.java index 7dfc5b6fe1e..902c9026587 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslConnection.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslConnection.java @@ -657,14 +657,8 @@ public class SslConnection extends AbstractConnection implements AsyncConnection while (now Date: Thu, 17 Nov 2011 10:35:14 +1100 Subject: [PATCH 2/5] avoid double request handling when suspended --- .../jetty/server/AsyncHttpConnection.java | 11 +++++--- ...xtTest.java => LocalAsyncContextTest.java} | 24 ++++++++++++----- .../server/SelectChannelAsyncContextTest.java | 26 +++++++++++++++++++ 3 files changed, 52 insertions(+), 9 deletions(-) rename jetty-server/src/test/java/org/eclipse/jetty/server/{AsyncContextTest.java => LocalAsyncContextTest.java} (94%) create mode 100644 jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelAsyncContextTest.java diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java index 36edce2440f..9ed2c33c166 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/AsyncHttpConnection.java @@ -111,14 +111,19 @@ public class AsyncHttpConnection extends AbstractHttpConnection implements Async reset(); - // TODO Is this required? + // TODO Is this still required? if (!_generator.isPersistent() && !_endp.isOutputShutdown()) { - LOG.warn("Safety net oshut!!!"); + LOG.warn("Safety net oshut!!! IF YOU SEE THIS, PLEASE RAISE BUGZILLA"); _endp.shutdownOutput(); } } - + else if (_request.getAsyncContinuation().isAsyncStarted()) + { + // The request is suspended, so even though progress has been made, break the while loop + LOG.debug("suspended {}",this); + break; + } } } } diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/AsyncContextTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/LocalAsyncContextTest.java similarity index 94% rename from jetty-server/src/test/java/org/eclipse/jetty/server/AsyncContextTest.java rename to jetty-server/src/test/java/org/eclipse/jetty/server/LocalAsyncContextTest.java index c0b85eb0a2c..e5b13f6dc52 100644 --- a/jetty-server/src/test/java/org/eclipse/jetty/server/AsyncContextTest.java +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/LocalAsyncContextTest.java @@ -31,16 +31,16 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; -public class AsyncContextTest +public class LocalAsyncContextTest { protected Server _server = new Server(); protected SuspendHandler _handler = new SuspendHandler(); - protected LocalConnector _connector; + protected Connector _connector; @Before public void init() throws Exception { - _connector = new LocalConnector(); + _connector = initConnector(); _server.setConnectors(new Connector[]{ _connector }); SessionHandler session = new SessionHandler(); @@ -49,6 +49,11 @@ public class AsyncContextTest _server.setHandler(session); _server.start(); } + + protected Connector initConnector() + { + return new LocalConnector(); + } @After public void destroy() throws Exception @@ -129,14 +134,21 @@ public class AsyncContextTest private synchronized String process(String content) throws Exception { - String request = "GET / HTTP/1.1\r\n" + "Host: localhost\r\n"; + String request = "GET / HTTP/1.1\r\n" + + "Host: localhost\r\n"+ + "Connection: close\r\n"; if (content==null) request+="\r\n"; else - request+="Content-Length: "+content.length()+"\r\n" + "\r\n" + content; + request+="Content-Length: "+content.length()+"\r\n" +"\r\n" + content; - return _connector.getResponses(request); + return getResponse(request); + } + + protected String getResponse(String request) throws Exception + { + return ((LocalConnector)_connector).getResponses(request); } private static class SuspendHandler extends HandlerWrapper diff --git a/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelAsyncContextTest.java b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelAsyncContextTest.java new file mode 100644 index 00000000000..35383e345cf --- /dev/null +++ b/jetty-server/src/test/java/org/eclipse/jetty/server/SelectChannelAsyncContextTest.java @@ -0,0 +1,26 @@ +package org.eclipse.jetty.server; + +import java.net.Socket; + +import org.eclipse.jetty.server.nio.SelectChannelConnector; +import org.eclipse.jetty.util.IO; + +public class SelectChannelAsyncContextTest extends LocalAsyncContextTest +{ + + @Override + protected Connector initConnector() + { + return new SelectChannelConnector(); + } + + @Override + protected String getResponse(String request) throws Exception + { + SelectChannelConnector connector = (SelectChannelConnector)_connector; + Socket socket = new Socket((String)null,connector.getLocalPort()); + socket.getOutputStream().write(request.getBytes("UTF-8")); + return IO.toString(socket.getInputStream()); + } + +} From 97c711613f751cafabcb9a6cf13913f0e1495143 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 17 Nov 2011 14:08:46 +1100 Subject: [PATCH 3/5] added siege like load tester --- .../eclipse/jetty/embedded/LikeJettyXml.java | 13 +- .../java/org/eclipse/jetty/client/Curl.java | 32 ++- .../java/org/eclipse/jetty/client/Siege.java | 194 ++++++++++++++++++ 3 files changed, 231 insertions(+), 8 deletions(-) create mode 100644 jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java diff --git a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java index 0cbb2b61afc..b9371e698c3 100644 --- a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java +++ b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java @@ -31,6 +31,7 @@ import org.eclipse.jetty.server.handler.RequestLogHandler; import org.eclipse.jetty.server.handler.StatisticsHandler; import org.eclipse.jetty.server.nio.SelectChannelConnector; import org.eclipse.jetty.server.ssl.SslSelectChannelConnector; +import org.eclipse.jetty.server.ssl.SslSocketConnector; import org.eclipse.jetty.util.log.Log; import org.eclipse.jetty.util.ssl.SslContextFactory; import org.eclipse.jetty.util.thread.QueuedThreadPool; @@ -63,7 +64,7 @@ public class LikeJettyXml connector.setPort(8080); connector.setMaxIdleTime(30000); connector.setConfidentialPort(8443); - connector.setStatsOn(true); + connector.setStatsOn(false); server.setConnectors(new Connector[] { connector }); @@ -86,11 +87,17 @@ public class LikeJettyXml "SSL_DHE_RSA_EXPORT_WITH_DES40_CBC_SHA", "SSL_DHE_DSS_EXPORT_WITH_DES40_CBC_SHA" }); - ssl_connector.setStatsOn(true); + ssl_connector.setStatsOn(false); server.addConnector(ssl_connector); ssl_connector.open(); - + SslSocketConnector ssl2_connector = new SslSocketConnector(cf); + ssl2_connector.setPort(8444); + ssl2_connector.setStatsOn(false); + server.addConnector(ssl2_connector); + ssl2_connector.open(); + + /* Ajp13SocketConnector ajp = new Ajp13SocketConnector(); diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/Curl.java b/jetty-client/src/test/java/org/eclipse/jetty/client/Curl.java index 1e7c1da3913..be0368b75c3 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/Curl.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/Curl.java @@ -1,6 +1,8 @@ package org.eclipse.jetty.client; import java.io.IOException; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.CountDownLatch; import java.util.concurrent.atomic.AtomicBoolean; @@ -33,11 +35,26 @@ public class Curl client.start(); boolean async=true; boolean dump= false; + boolean verbose= false; - final CountDownLatch latch = new CountDownLatch(args.length); + + int urls=0; + for (String arg : args) + { + if (!arg.startsWith("-")) + urls++; + } + + final CountDownLatch latch = new CountDownLatch(urls); for (String arg : args) { + if ("--verbose".equals(arg)) + { + verbose=true; + continue; + } + if ("--sync".equals(arg)) { async=false; @@ -63,6 +80,7 @@ public class Curl } final boolean d = dump; + final boolean v = verbose; HttpExchange ex = new HttpExchange() { AtomicBoolean counted=new AtomicBoolean(false); @@ -105,7 +123,8 @@ public class Curl super.onResponseContent(content); if (d) System.out.print(content.toString()); - System.err.println("got "+content.length()); + if (v) + System.err.println("got "+content.length()); } /* ------------------------------------------------------------ */ @@ -116,7 +135,8 @@ public class Curl protected void onResponseHeader(Buffer name, Buffer value) throws IOException { super.onResponseHeader(name,value); - System.err.println(name+": "+value); + if (v) + System.err.println(name+": "+value); } /* ------------------------------------------------------------ */ @@ -127,7 +147,8 @@ public class Curl protected void onResponseHeaderComplete() throws IOException { super.onResponseHeaderComplete(); - System.err.println(); + if (v) + System.err.println(); } /* ------------------------------------------------------------ */ @@ -138,7 +159,8 @@ public class Curl protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException { super.onResponseStatus(version,status,reason); - System.err.println(version+" "+status+" "+reason); + if (v) + System.err.println(version+" "+status+" "+reason); } }; diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java b/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java new file mode 100644 index 00000000000..d8fa2f9585c --- /dev/null +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java @@ -0,0 +1,194 @@ +package org.eclipse.jetty.client; + +import java.io.IOException; +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.CountDownLatch; +import java.util.concurrent.atomic.AtomicBoolean; + +import org.eclipse.jetty.http.HttpMethods; +import org.eclipse.jetty.io.Buffer; + + +/* ------------------------------------------------------------ */ +/** + */ +public class Siege +{ + private static final class ConcurrentExchange extends HttpExchange + { + private final long _start=System.currentTimeMillis(); + private final HttpClient _client; + private final CountDownLatch _latch; + volatile int _status; + volatile int _count; + final List _uris; + final int _repeats; + int _u; + int _r; + + AtomicBoolean counted=new AtomicBoolean(false); + + public ConcurrentExchange(HttpClient client,CountDownLatch latch, List uris, int repeats) + { + _client = client; + _latch = latch; + _uris = uris; + _repeats = repeats; + } + + @Override + protected void onConnectionFailed(Throwable ex) + { + if (!counted.getAndSet(true)) + _latch.countDown(); + super.onConnectionFailed(ex); + } + + @Override + protected void onException(Throwable ex) + { + if (!counted.getAndSet(true)) + _latch.countDown(); + super.onException(ex); + } + + @Override + protected void onExpire() + { + if (!counted.getAndSet(true)) + _latch.countDown(); + super.onExpire(); + } + + @Override + protected void onResponseComplete() throws IOException + { + if (_status==200) + _count++; + if (!next() && !counted.getAndSet(true)) + { + _latch.countDown(); + long duration=System.currentTimeMillis()-_start; + System.err.printf("Got %d/%d in %dms %d%n",_count,_uris.size()*_repeats,duration,_latch.getCount()); + } + } + + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.client.HttpExchange#onResponseHeader(org.eclipse.jetty.io.Buffer, org.eclipse.jetty.io.Buffer) + */ + @Override + protected void onResponseHeader(Buffer name, Buffer value) throws IOException + { + super.onResponseHeader(name,value); + if ("Set-Cookie".equalsIgnoreCase(name.toString())) + { + String v=value.toString(); + int c = v.indexOf(';'); + if (c>=0) + v=v.substring(0,c); + addRequestHeader("Cookie",v); + } + } + + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.client.HttpExchange#onResponseHeaderComplete() + */ + @Override + protected void onResponseHeaderComplete() throws IOException + { + super.onResponseHeaderComplete(); + } + + /* ------------------------------------------------------------ */ + /** + * @see org.eclipse.jetty.client.HttpExchange#onResponseStatus(org.eclipse.jetty.io.Buffer, int, org.eclipse.jetty.io.Buffer) + */ + @Override + protected void onResponseStatus(Buffer version, int status, Buffer reason) throws IOException + { + _status=status; + super.onResponseStatus(version,status,reason); + } + + public boolean next() + { + if (_u>=_uris.size()) + { + _u=0; + _r++; + if (_r>=_repeats) + return false; + } + + String uri=_uris.get(_u++); + + reset(); + setMethod(HttpMethods.GET); + setURL(uri); + + try + { + _client.send(this); + } + catch(IOException e) + { + e.printStackTrace(); + return false; + } + return true; + } + } + + public static void main(String[] args) + throws Exception + { + if (args.length==0) + args=new String[] + { "-c", "2", "-r", "2", "http://localhost:8080/dump", "http://localhost:8080/d.txt"}; + + int concurrent=1; + int repeats=1; + final List uris = new ArrayList(); + + for (int i=0; i Date: Thu, 17 Nov 2011 14:45:41 +1100 Subject: [PATCH 4/5] improved siege like load tester --- .../test/java/org/eclipse/jetty/client/Siege.java | 12 +++++++++++- .../eclipse/jetty/server/BlockingHttpConnection.java | 3 ++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java b/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java index d8fa2f9585c..62d4347b346 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java @@ -22,6 +22,7 @@ public class Siege private final CountDownLatch _latch; volatile int _status; volatile int _count; + volatile long _bytes; final List _uris; final int _repeats; int _u; @@ -70,9 +71,18 @@ public class Siege { _latch.countDown(); long duration=System.currentTimeMillis()-_start; - System.err.printf("Got %d/%d in %dms %d%n",_count,_uris.size()*_repeats,duration,_latch.getCount()); + System.err.printf("Got %d/%d with %dB in %dms %d%n",_count,_uris.size()*_repeats,_bytes,duration,_latch.getCount()); } } + + + /* ------------------------------------------------------------ */ + @Override + protected void onResponseContent(Buffer content) throws IOException + { + _bytes+=content.length(); + super.onResponseContent(content); + } /* ------------------------------------------------------------ */ /** diff --git a/jetty-server/src/main/java/org/eclipse/jetty/server/BlockingHttpConnection.java b/jetty-server/src/main/java/org/eclipse/jetty/server/BlockingHttpConnection.java index eb8f4a6dc63..20797d9a62c 100644 --- a/jetty-server/src/main/java/org/eclipse/jetty/server/BlockingHttpConnection.java +++ b/jetty-server/src/main/java/org/eclipse/jetty/server/BlockingHttpConnection.java @@ -102,6 +102,7 @@ public class BlockingHttpConnection extends AbstractHttpConnection // Reset the parser/generator progress=true; reset(); + _endp.flush(); // look for a switched connection instance? if (_response.getStatus()==HttpStatus.SWITCHING_PROTOCOLS_101) @@ -114,7 +115,7 @@ public class BlockingHttpConnection extends AbstractHttpConnection // TODO Is this required? if (!_generator.isPersistent() && !_endp.isOutputShutdown()) { - System.err.println("Safety net oshut!!!"); + LOG.warn("Safety net oshut!!! Please open a bugzilla"); _endp.shutdownOutput(); } } From 584bbd4bceb3303a3d8a96308470f702b20c04b1 Mon Sep 17 00:00:00 2001 From: Greg Wilkins Date: Thu, 17 Nov 2011 16:31:22 +1100 Subject: [PATCH 5/5] improved siege --- .../main/java/org/eclipse/jetty/embedded/LikeJettyXml.java | 2 +- .../src/test/java/org/eclipse/jetty/client/Siege.java | 7 +++++++ .../main/java/org/eclipse/jetty/io/nio/SslConnection.java | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java index b9371e698c3..899c682bc08 100644 --- a/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java +++ b/example-jetty-embedded/src/main/java/org/eclipse/jetty/embedded/LikeJettyXml.java @@ -56,7 +56,7 @@ public class LikeJettyXml // Setup Threadpool QueuedThreadPool threadPool = new QueuedThreadPool(); - threadPool.setMaxThreads(100); + threadPool.setMaxThreads(500); server.setThreadPool(threadPool); // Setup Connectors diff --git a/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java b/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java index 62d4347b346..bc476c27fc7 100644 --- a/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java +++ b/jetty-client/src/test/java/org/eclipse/jetty/client/Siege.java @@ -8,6 +8,7 @@ import java.util.concurrent.atomic.AtomicBoolean; import org.eclipse.jetty.http.HttpMethods; import org.eclipse.jetty.io.Buffer; +import org.eclipse.jetty.util.thread.QueuedThreadPool; /* ------------------------------------------------------------ */ @@ -181,8 +182,12 @@ public class Siege uris.add(arg); } + QueuedThreadPool pool = new QueuedThreadPool(); + pool.setMaxThreads(500); + pool.setDaemon(true); HttpClient client = new HttpClient(); + client.setThreadPool(pool); client.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL); client.setIdleTimeout(30000); client.setConnectTimeout(30000); @@ -200,5 +205,7 @@ public class Siege } latch.await(); + client.stop(); + pool.stop(); } } diff --git a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslConnection.java b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslConnection.java index 902c9026587..fa2b72e2c15 100644 --- a/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslConnection.java +++ b/jetty-io/src/main/java/org/eclipse/jetty/io/nio/SslConnection.java @@ -793,7 +793,7 @@ public class SslConnection extends AbstractConnection implements AsyncConnection o=_outbound; u=_unwrapBuf; } - return "SSL:"+_endp+" "+_engine.getHandshakeStatus()+" i/u/o="+(i==null?0:i.length())+"/"+(u==null?0:u.length())+"/"+(o==null?0:o.length()+(_oshut?" oshut":"")); + return "SSL:"+_endp+" "+_engine.getHandshakeStatus()+" i/u/o="+(i==null?0:i.length())+"/"+(u==null?0:u.length())+"/"+(o==null?0:o.length()+(_ishut?" ishut":"")+(_oshut?" oshut":"")); } }