tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From sebb <seb...@gmail.com>
Subject Re: svn commit: r1051202 - in /tomcat/trunk: java/org/apache/tomcat/util/net/JIoEndpoint.java test/org/apache/catalina/connector/TestMaxConnections.java test/org/apache/catalina/startup/SimpleHttpClient.java webapps/docs/config/http.xml
Date Mon, 20 Dec 2010 19:57:07 GMT
On 20 December 2010 16:42,  <fhanik@apache.org> wrote:
> Author: fhanik
> Date: Mon Dec 20 16:42:13 2010
> New Revision: 1051202
>
> URL: http://svn.apache.org/viewvc?rev=1051202&view=rev
> Log:
> Implement a maxConnection threshold for the JIoEndpoint, to be able to constraint how
many connections the connector will accept
>
> Added:
>    tomcat/trunk/test/org/apache/catalina/connector/TestMaxConnections.java   (with
props)
> Modified:
>    tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java
>    tomcat/trunk/test/org/apache/catalina/startup/SimpleHttpClient.java
>    tomcat/trunk/webapps/docs/config/http.xml
>
> Modified: tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java
> URL: http://svn.apache.org/viewvc/tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java?rev=1051202&r1=1051201&r2=1051202&view=diff
> ==============================================================================
> --- tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java (original)
> +++ tomcat/trunk/java/org/apache/tomcat/util/net/JIoEndpoint.java Mon Dec 20 16:42:13
2010
> @@ -32,6 +32,7 @@ import org.apache.juli.logging.Log;
>  import org.apache.juli.logging.LogFactory;
>  import org.apache.tomcat.util.ExceptionUtils;
>  import org.apache.tomcat.util.net.AbstractEndpoint.Handler.SocketState;
> +import org.apache.tomcat.util.threads.CounterLatch;
>
>
>  /**
> @@ -107,6 +108,8 @@ public class JIoEndpoint extends Abstrac
>         // Not supported
>         return false;
>     }
> +
> +    protected CounterLatch connectionCounterLatch = null;

Could this be private?

>
>
>     // ------------------------------------------------ Handler Inner Interface
> @@ -197,20 +200,24 @@ public class JIoEndpoint extends Abstrac
>                     break;
>                 }
>                 try {
> +                    //if we have reached max connections, wait
> +                    connectionCounterLatch.await();
>                     // Accept the next incoming connection from the server
socket
>                     Socket socket = serverSocketFactory.acceptSocket(serverSocket);
>
>                     // Configure the socket
>                     if (setSocketOptions(socket)) {
> -                    // Hand this socket off to an appropriate processor
> -                    if (!processSocket(socket)) {
> -                        // Close socket right away
> -                        try {
> -                            socket.close();
> -                        } catch (IOException e) {
> -                            // Ignore
> +                        // Hand this socket off to an appropriate processor
> +                        if (!processSocket(socket)) {
> +                            // Close socket right away
> +                            try {
> +                                socket.close();
> +                            } catch (IOException e) {
> +                                // Ignore
> +                            }
> +                        } else {
> +                            connectionCounterLatch.countUp();
>                         }
> -                    }
>                     } else {
>                         // Close socket right away
>                         try {
> @@ -286,6 +293,7 @@ public class JIoEndpoint extends Abstrac
>                         if (log.isTraceEnabled()) {
>                             log.trace("Closing socket:"+socket);
>                         }
> +                        connectionCounterLatch.countDown();
>                         try {
>                             socket.getSocket().close();
>                         } catch (IOException e) {
> @@ -373,6 +381,8 @@ public class JIoEndpoint extends Abstrac
>             if (getExecutor() == null) {
>                 createExecutor();
>             }
> +
> +            connectionCounterLatch = new CounterLatch(0,getMaxConnections());
>
>             // Start acceptor threads
>             for (int i = 0; i < acceptorThreadCount; i++) {
> @@ -394,6 +404,8 @@ public class JIoEndpoint extends Abstrac
>
>     @Override
>     public void stopInternal() {
> +        connectionCounterLatch.releaseAll();
> +        connectionCounterLatch = null;
>         if (!paused) {
>             pause();
>         }
>
> Added: tomcat/trunk/test/org/apache/catalina/connector/TestMaxConnections.java
> URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/connector/TestMaxConnections.java?rev=1051202&view=auto
> ==============================================================================
> --- tomcat/trunk/test/org/apache/catalina/connector/TestMaxConnections.java (added)
> +++ tomcat/trunk/test/org/apache/catalina/connector/TestMaxConnections.java Mon Dec 20
16:42:13 2010
> @@ -0,0 +1,180 @@
> +/*
> + *  Licensed to the Apache Software Foundation (ASF) under one or more
> + *  contributor license agreements.  See the NOTICE file distributed with
> + *  this work for additional information regarding copyright ownership.
> + *  The ASF licenses this file to You under the Apache License, Version 2.0
> + *  (the "License"); you may not use this file except in compliance with
> + *  the License.  You may obtain a copy of the License at
> + *
> + *      http://www.apache.org/licenses/LICENSE-2.0
> + *
> + *  Unless required by applicable law or agreed to in writing, software
> + *  distributed under the License is distributed on an "AS IS" BASIS,
> + *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
> + *  See the License for the specific language governing permissions and
> + *  limitations under the License.
> + */
> +package org.apache.catalina.connector;
> +
> +import java.io.IOException;
> +
> +import javax.servlet.ServletException;
> +import javax.servlet.http.HttpServlet;
> +import javax.servlet.http.HttpServletRequest;
> +import javax.servlet.http.HttpServletResponse;
> +
> +import org.apache.catalina.Context;
> +import org.apache.catalina.startup.SimpleHttpClient;
> +import org.apache.catalina.startup.Tomcat;
> +import org.apache.catalina.startup.TomcatBaseTest;
> +
> +public class TestMaxConnections extends TomcatBaseTest{
> +
> +    Tomcat tomcat = null;
> +    static int soTimeout = 3000;
> +    static int connectTimeout = 1000;
> +
> +    public void test1() throws Exception {
> +        init();
> +        start();
> +        ConnectThread[] t = new ConnectThread[10];
> +        int passcount = 0;
> +        int connectfail = 0;
> +        for (int i=0; i<t.length; i++) {
> +            t[i] = new ConnectThread();
> +            t[i].setName("ConnectThread["+i+"+]");
> +            t[i].start();
> +        }
> +        for (int i=0; i<t.length; i++) {
> +            t[i].join();
> +            if (t[i].passed) passcount++;
> +            if (t[i].connectfailed) connectfail++;
> +        }
> +        assertEquals("The number of successful requests should have been 5.",5,
passcount);
> +        assertEquals("The number of failed connects should have been 5.",5, connectfail);
> +        stop();
> +    }
> +
> +
> +    private class ConnectThread extends Thread {
> +        public boolean passed = true;
> +        public boolean connectfailed = false;
> +        public void run() {
> +            try {
> +                TestKeepAliveClient client = new TestKeepAliveClient();
> +                client.doHttp10Request();
> +            }catch (Exception x) {
> +                passed = false;
> +                System.err.println(Thread.currentThread().getName()+" Error:"+x.getMessage());
> +                connectfailed = "connect timed out".equals(x.getMessage());
> +            }
> +        }
> +    }
> +
> +    private boolean init;
> +
> +    private synchronized void init() {
> +        if (init) return;
> +
> +        Tomcat tomcat = getTomcatInstance();
> +        Context root = tomcat.addContext("", SimpleHttpClient.TEMP_DIR);
> +        Tomcat.addServlet(root, "Simple", new SimpleServlet());
> +        root.addServletMapping("/test", "Simple");
> +        tomcat.getConnector().setProperty("maxKeepAliveRequests", "5");
> +        tomcat.getConnector().setProperty("soTimeout", "20000");
> +        tomcat.getConnector().setProperty("keepAliveTimeout", "50000");
> +        tomcat.getConnector().setProperty("port", "8080");
> +        tomcat.getConnector().setProperty("maxConnections", "4");
> +        tomcat.getConnector().setProperty("acceptCount", "1");
> +        init = true;
> +    }
> +
> +    private synchronized void start() throws Exception {
> +        tomcat = getTomcatInstance();
> +        init();
> +        tomcat.start();
> +    }
> +
> +    private synchronized void stop() throws Exception {
> +        tomcat.stop();
> +    }
> +
> +    private class TestKeepAliveClient extends SimpleHttpClient {
> +
> +        private void doHttp10Request() throws Exception {
> +
> +            long start = System.currentTimeMillis();
> +            // Open connection
> +            connect(connectTimeout,soTimeout);
> +
> +            // Send request in two parts
> +            String[] request = new String[1];
> +            request[0] =
> +                "GET /test HTTP/1.0" + CRLF + CRLF;
> +            setRequest(request);
> +            boolean passed = false;
> +            processRequest(false); // blocks until response has been read
> +            long stop = System.currentTimeMillis();
> +            System.out.println(Thread.currentThread().getName()+" Request complete:"+(stop-start)+"
ms.");
> +            passed = (this.readLine()==null);
> +            // Close the connection
> +            disconnect();
> +            reset();
> +            assertTrue(passed);
> +        }
> +
> +        private void doHttp11Request() throws Exception {
> +            Tomcat tomcat = getTomcatInstance();
> +            init();
> +            tomcat.start();
> +            // Open connection
> +            connect();
> +
> +            // Send request in two parts
> +            String[] request = new String[1];
> +            request[0] =
> +                "GET /test HTTP/1.1" + CRLF +
> +                "Host: localhost" + CRLF +
> +                "Connection: Keep-Alive" + CRLF+
> +                "Keep-Alive: 300"+ CRLF+ CRLF;
> +
> +            setRequest(request);
> +
> +            for (int i=0; i<5; i++) {
> +                processRequest(false); // blocks until response has been read
> +                assertTrue(getResponseLine()!=null && getResponseLine().trim().startsWith("HTTP/1.1
200"));
> +            }
> +            boolean passed = (this.readLine()==null);
> +            // Close the connection
> +            disconnect();
> +            reset();
> +            tomcat.stop();
> +            assertTrue(passed);
> +        }
> +
> +        @Override
> +        public boolean isResponseBodyOK() {
> +            return true;
> +        }
> +
> +    }
> +
> +
> +    private static class SimpleServlet extends HttpServlet {
> +
> +        private static final long serialVersionUID = 1L;
> +
> +        @Override
> +        protected void service(HttpServletRequest req, HttpServletResponse resp)
throws ServletException, IOException {
> +            try {
> +                Thread.sleep(TestMaxConnections.soTimeout/2);
> +            }catch (InterruptedException x) {
> +
> +            }
> +            resp.setContentLength(0);
> +            resp.flushBuffer();
> +        }
> +
> +    }
> +
> +}
>
> Propchange: tomcat/trunk/test/org/apache/catalina/connector/TestMaxConnections.java
> ------------------------------------------------------------------------------
>    svn:eol-style = native
>
> Modified: tomcat/trunk/test/org/apache/catalina/startup/SimpleHttpClient.java
> URL: http://svn.apache.org/viewvc/tomcat/trunk/test/org/apache/catalina/startup/SimpleHttpClient.java?rev=1051202&r1=1051201&r2=1051202&view=diff
> ==============================================================================
> --- tomcat/trunk/test/org/apache/catalina/startup/SimpleHttpClient.java (original)
> +++ tomcat/trunk/test/org/apache/catalina/startup/SimpleHttpClient.java Mon Dec 20 16:42:13
2010
> @@ -25,7 +25,9 @@ import java.io.OutputStream;
>  import java.io.OutputStreamWriter;
>  import java.io.Reader;
>  import java.io.Writer;
> +import java.net.InetSocketAddress;
>  import java.net.Socket;
> +import java.net.SocketAddress;
>  import java.net.UnknownHostException;
>  import java.util.ArrayList;
>  import java.util.List;
> @@ -109,14 +111,20 @@ public abstract class SimpleHttpClient {
>         return null;
>     }
>
> -    public void connect() throws UnknownHostException, IOException {
> -        socket = new Socket("localhost", port);
> +    public void connect(int connectTimeout, int soTimeout) throws UnknownHostException,
IOException {
> +        SocketAddress addr = new InetSocketAddress("localhost", port);
> +        socket = new Socket();
> +        socket.setSoTimeout(soTimeout);
> +        socket.connect(addr,connectTimeout);
>         OutputStream os = socket.getOutputStream();
>         writer = new OutputStreamWriter(os);
>         InputStream is = socket.getInputStream();
>         Reader r = new InputStreamReader(is);
>         reader = new BufferedReader(r);
>     }
> +    public void connect() throws UnknownHostException, IOException {
> +        connect(0,0);
> +    }
>
>     public void processRequest() throws IOException, InterruptedException {
>         processRequest(true);
>
> Modified: tomcat/trunk/webapps/docs/config/http.xml
> URL: http://svn.apache.org/viewvc/tomcat/trunk/webapps/docs/config/http.xml?rev=1051202&r1=1051201&r2=1051202&view=diff
> ==============================================================================
> --- tomcat/trunk/webapps/docs/config/http.xml (original)
> +++ tomcat/trunk/webapps/docs/config/http.xml Mon Dec 20 16:42:13 2010
> @@ -361,6 +361,15 @@
>       execute tasks using the executor rather than an internal thread pool.</p>
>     </attribute>
>
> +    <attribute name="maxConnections" required="false">
> +      <p>The maximum number of connections that the server will accept and
process
> +      at any given time. When this number has been reached, the server will not accept
any more
> +      connections until the number of connections reach below this value. The operating
system may still accept connections based
> +      on the <code>acceptCount</code> setting.
> +      This setting is currently only applicable to the blocking Java connectors (AJP/HTTP).
> +      Default value is <code>10000</code>.</p>
> +    </attribute>
> +
>     <attribute name="maxTrailerSize" required="false">
>       <p>Limits the total length of trailing headers in the last chunk of
>       a chunked HTTP request. If the value is <code>-1</code>, no limit
will be
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
> For additional commands, e-mail: dev-help@tomcat.apache.org
>
>

---------------------------------------------------------------------
To unsubscribe, e-mail: dev-unsubscribe@tomcat.apache.org
For additional commands, e-mail: dev-help@tomcat.apache.org


Mime
View raw message