On 20 December 2010 16:42, <[email protected]> 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: [email protected]
> For additional commands, e-mail: [email protected]
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]