Hi,
I am new to HTTP Components. I wrote a short server which is based on the
Asynchronous HTTP Server example. I am using httpcore-4.2.2 and
httpcore-nio-4.2.2. I wrote a short test program that loads my server. I
see that after ~500,000 requests I get a socket leak of ~600 sockets. I got
84 SocketTimeoutException during the test. After I got to a big number of
leak sockets the application stopped responding and I couldn't even connect
to it with remote debugger.
bellow is my test.
Regards,
Nir
/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package httpsample;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.InterruptedIOException;
import java.net.InetSocketAddress;
import java.net.URL;
import java.security.KeyStore;
import java.util.Calendar;
import java.util.logging.Level;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpException;
import org.apache.http.HttpRequest;
import org.apache.http.HttpResponse;
import org.apache.http.HttpResponseInterceptor;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.nio.DefaultHttpServerIODispatch;
import org.apache.http.impl.nio.DefaultNHttpServerConnection;
import org.apache.http.impl.nio.DefaultNHttpServerConnectionFactory;
import org.apache.http.impl.nio.SSLNHttpServerConnectionFactory;
import org.apache.http.impl.nio.reactor.DefaultListeningIOReactor;
import org.apache.http.impl.nio.reactor.IOReactorConfig;
import org.apache.http.nio.NHttpConnectionFactory;
import org.apache.http.nio.NHttpServerConnection;
import org.apache.http.nio.protocol.BasicAsyncRequestConsumer;
import org.apache.http.nio.protocol.BasicAsyncResponseProducer;
import org.apache.http.nio.protocol.HttpAsyncExchange;
import org.apache.http.nio.protocol.HttpAsyncRequestConsumer;
import org.apache.http.nio.protocol.HttpAsyncRequestHandler;
import org.apache.http.nio.protocol.HttpAsyncRequestHandlerRegistry;
import org.apache.http.nio.protocol.HttpAsyncResponseProducer;
import org.apache.http.nio.protocol.HttpAsyncService;
import org.apache.http.nio.reactor.IOEventDispatch;
import org.apache.http.nio.reactor.ListeningIOReactor;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.params.SyncBasicHttpParams;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpProcessor;
import org.apache.http.protocol.ImmutableHttpProcessor;
import org.apache.http.protocol.ResponseConnControl;
import org.apache.http.protocol.ResponseContent;
import org.apache.http.protocol.ResponseDate;
import org.apache.http.protocol.ResponseServer;
import org.apache.log4j.xml.DOMConfigurator;

/**
 * HTTP/1.1 file server based on the non-blocking I/O model and capable of
direct channel
 * (zero copy) data transfer.
 */
public class Httpsample {
    static private org.apache.log4j.Logger log =
org.apache.log4j.Logger.getLogger(Httpsample.class.getName());
    static private final int DFLT_NUM_WORKERS = 200;
    static private final int DFLT_PORT = 20003;
    static public boolean STAND_ALONE = false;
    public static void main(String[] args) throws Exception {
        int numOfWorkers = DFLT_NUM_WORKERS;
        int port = DFLT_PORT;
        for ( int i = 0; i < args.length; i++) {
            switch (i){
                    case 0:
                        port = Integer.parseInt(args[i]);
                        break;
                    case 1:
                        numOfWorkers = Integer.parseInt(args[i]);
                        break;
                    case 2:
                        STAND_ALONE = true;
                        break;
            }
        }
//        start log4j system
        Calendar now = Calendar.getInstance();
        System.setProperty("log4j.year",
Integer.toString(now.get(Calendar.YEAR)));
        System.setProperty("log4j.month",
Integer.toString(now.get(Calendar.MONTH) + 1));
        System.setProperty("log4j.day",
Integer.toString(now.get(Calendar.DATE)));
        System.setProperty("log4j.hours",
Integer.toString(now.get(Calendar.HOUR_OF_DAY)));
        System.setProperty("log4j.minutes",
Integer.toString(now.get(Calendar.MINUTE)));
        System.setProperty("log4j.seconds",
Integer.toString(now.get(Calendar.SECOND)));
        DOMConfigurator.configure("log.xml");

        // HTTP parameters for the server
        HttpParams params = new SyncBasicHttpParams();
        params
            .setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 20000)
            .setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 *
1024)
            .setParameter(CoreProtocolPNames.ORIGIN_SERVER, "VascoDE/1.1");
        // Create HTTP protocol processing chain
        HttpProcessor httpproc = new ImmutableHttpProcessor(new
HttpResponseInterceptor[] {
                // Use standard server-side protocol interceptors
                new ResponseDate(),
                new ResponseServer(),
                new ResponseContent(),
                new ResponseConnControl()
        });
        // Create request handler registry
        HttpAsyncRequestHandlerRegistry reqistry = new
HttpAsyncRequestHandlerRegistry();
        // Register the default handler for all URIs
        reqistry.register("*", new HttpFileHandler());
        // Create server-side HTTP protocol handler
        HttpAsyncService protocolHandler = new HttpAsyncService(
                httpproc, new DefaultConnectionReuseStrategy(), reqistry,
params) {

            @Override
            public void connected(final NHttpServerConnection conn) {
                System.out.println(conn + ": connection open");
                super.connected(conn);
            }

            @Override
            public void closed(final NHttpServerConnection conn) {
                System.out.println(conn + ": connection closed");
                super.closed(conn);
            }

        };
        // Create HTTP connection factory
        NHttpConnectionFactory<DefaultNHttpServerConnection> connFactory;
        if (port == 8443) {
            // Initialize SSL context
            ClassLoader cl = Httpsample.class.getClassLoader();
            URL url = cl.getResource("my.keystore");
            if (url == null) {
                System.out.println("Keystore not found");
                System.exit(1);
            }
            KeyStore keystore  = KeyStore.getInstance("jks");
            keystore.load(url.openStream(), "secret".toCharArray());
            KeyManagerFactory kmfactory = KeyManagerFactory.getInstance(
                    KeyManagerFactory.getDefaultAlgorithm());
            kmfactory.init(keystore, "secret".toCharArray());
            KeyManager[] keymanagers = kmfactory.getKeyManagers();
            SSLContext sslcontext = SSLContext.getInstance("TLS");
            sslcontext.init(keymanagers, null, null);
            connFactory = new SSLNHttpServerConnectionFactory(sslcontext,
null, params);
        } else {
            connFactory = new DefaultNHttpServerConnectionFactory(params);
        }
        // Create server-side I/O event dispatch
        IOEventDispatch ioEventDispatch = new
DefaultHttpServerIODispatch(protocolHandler, connFactory);
        // Create server-side I/O reactor
        IOReactorConfig conf = new IOReactorConfig();
        conf.setIoThreadCount(numOfWorkers);
        ListeningIOReactor ioReactor = new DefaultListeningIOReactor(conf);
        try {
            // Listen of the given port
            ioReactor.listen(new InetSocketAddress(port));
            // Ready to go!
            ioReactor.execute(ioEventDispatch);
        } catch (InterruptedIOException ex) {
            System.err.println("Interrupted");
        } catch (IOException e) {
            System.err.println("I/O error: " + e.getMessage());
        }
        System.out.println("Shutdown");
    }

    static class HttpFileHandler implements
HttpAsyncRequestHandler<HttpRequest> {


        public HttpFileHandler() {
            super();
        }

        @Override
        public HttpAsyncRequestConsumer<HttpRequest> processRequest(
                final HttpRequest request,
                final HttpContext context) {
            // Buffer request content in memory for simplicity
            return new BasicAsyncRequestConsumer();
        }
            class testResProducer extends BasicAsyncResponseProducer {

            public testResProducer(HttpResponse response) {
                super(response);
            }

            @Override
            public synchronized HttpResponse generateResponse() {
                log.debug("generating response - producer" + this);
                //return super.generateResponse();
                                HttpResponse res = super.generateResponse();
                log.debug("generated response - producer" + this);
                return res;
            }

            @Override
            public void failed(Exception ex) {
                log.error( "failed to send response- producer" + this, ex);
                super.failed(ex);
            }

            }


        @Override
        public void handle(
                final HttpRequest request,
                final HttpAsyncExchange httpexchange,
                final HttpContext context) throws HttpException,
IOException {
            HttpResponse response = httpexchange.getResponse();
            try {
              String method = request.getRequestLine().getMethod();
              if ( method.equals("POST")) {
                new
POSTHandler().processRequest((HttpEntityEnclosingRequest)request,
response);
              } else {
                new GETHandler().processRequest(request, response);

              }
            }catch (Exception ex)  {
                log.error("failed to submit response", ex);
                response.setStatusCode(500);
            }
            HttpAsyncResponseProducer producer = new
testResProducer(response);
            log.debug("submiting responce with producer" + producer);
            httpexchange.submitResponse(producer);
        }
   }

}

Reply via email to