You are viewing a plain text version of this content. The canonical link for it is here.
Posted to httpclient-users@hc.apache.org by Nir Dweck <ni...@vasco-de.com> on 2012/12/16 12:03:08 UTC

Socket leak of Async HTTP server

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);
        }
   }

}

Re: PoolingClientConnectionManager how to close a selected connection

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Tue, 2012-12-18 at 09:24 +0000, Alex wrote:
> Hi,
> I'm using PoolingClientConnectionManager to obtain a HttpClient and after execute a HttpPost where I set 1 to max for the pool.
> 
> Looking at connection state with netstat I see the connection status in ESTABLISHED (and this is the right behavoir that I expect) for all my test.
> How is possible to force PoolingClientConnectionManager  to close a specifice connection and recreate a new one ?
> In my code I tried to use releaseConnection() but the status not change in the netstatlist and if I use httpClient.getConnectionManager().shutdown() (used previously to kill the connection but with not Pooled connection ) the PoolingClientConnectionManager became not working
> 
> 
> Thank you very much

You can use a custom keep alive strategy and set the keep-alive period
for persistent connections to some finite value in milliseconds.
Persistent connections will not be re-used once that period expires. You
can also use #closeExpiredConnections() of the connection manager to
pro-actively evict expired connections from the pool.

Hope this helps

Oleg  


---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-users-unsubscribe@hc.apache.org
For additional commands, e-mail: httpclient-users-help@hc.apache.org


PoolingClientConnectionManager how to close a selected connection

Posted by Alex <ga...@yahoo.com>.
Hi,
I'm using PoolingClientConnectionManager to obtain a HttpClient and after execute a HttpPost where I set 1 to max for the pool.

Looking at connection state with netstat I see the connection status in ESTABLISHED (and this is the right behavoir that I expect) for all my test.
How is possible to force PoolingClientConnectionManager  to close a specifice connection and recreate a new one ?
In my code I tried to use releaseConnection() but the status not change in the netstatlist and if I use httpClient.getConnectionManager().shutdown() (used previously to kill the connection but with not Pooled connection ) the PoolingClientConnectionManager became not working


Thank you very much

Re: Socket leak of Async HTTP server

Posted by Nir Dweck <ni...@vasco-de.com>.
Oleg,
Thanks for the response.
The code doesn't compile because i didn't add my logic classes. In any case
I think I found the problem and it has nothing to do with the HTTPCore. My
application is a GW to a system and someone "forgot" that he run a new
process that accidentally sometimes stuck the system which affected my GW,
he just "remembered' it this morning. I have a stand alone test which
worked fine all the time, which was the reason I was so puzzled by the
problem and asked the forum if anyone has run into such a problem.
Regards,
Nir


On Sun, Dec 16, 2012 at 6:01 PM, Oleg Kalnichevski <ol...@apache.org> wrote:

> On Sun, 2012-12-16 at 13:03 +0200, Nir Dweck wrote:
> > 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
>
> Nir
>
> Your code does not compile so I cannot test it. I know that HttpCore
> (both blocking and non-blocking) can easily handle millions of requests.
> There is an (non-scientific) HTTP micro-benchmark used by the project to
> test HttpCore's performance [1]. Based on it 1'000'000 request do not
> seem to pose any sort of issue.
>
> Feel free to tweak the micro-benchmark and see how it performs for you
>
> Oleg
>
> [1]
> http://svn.apache.org/repos/asf/httpcomponents/benchmark/httpcore/trunk/
>
> ---------------------------------------------------------------
> HttpCore (blocking I/O); version: 4.2.3
> ---------------------------------------------------------------
>
> Server Software:                HttpCore-Test/1.1
> Server Hostname:                localhost
> Server Port:                    8989
>
> Document Path:                  http://localhost:8989/rnd?c=2048
> Document Length:                2048 bytes
>
> Concurrency Level:              10
> Time taken for tests:           9.889423 seconds
> Complete requests:              1000000
> Failed requests:                0
> Write errors:                   0
> Kept alive:                     1000000
> Total transferred:              2048000000 bytes
> Requests per second:            101,118.13 [#/sec] (mean)
> Time per request:               0.099 [ms] (mean)
> Time per request:               0.010 [ms] (mean, across all concurrent
> requests)
> Transfer rate:                  207,089.94 [Kbytes/sec] received
>                                 -1 kb/s sent
>                                 207,089.94 kb/s total
> ---------------------------------------------------------------
> ---------------------------------------------------------------
> HttpCore (NIO); version: 4.2.3
> ---------------------------------------------------------------
>
> Server Software:                HttpCore-NIO-Test/1.1
> Server Hostname:                localhost
> Server Port:                    8989
>
> Document Path:                  http://localhost:8989/rnd?c=2048
> Document Length:                2048 bytes
>
> Concurrency Level:              10
> Time taken for tests:           20.235072 seconds
> Complete requests:              1000000
> Failed requests:                0
> Write errors:                   0
> Kept alive:                     1000000
> Total transferred:              2048000000 bytes
> Requests per second:            49,419.15 [#/sec] (mean)
> Time per request:               0.202 [ms] (mean)
> Time per request:               0.020 [ms] (mean, across all concurrent
> requests)
> Transfer rate:                  101,210.41 [Kbytes/sec] received
>                                 -1 kb/s sent
>                                 101,210.41 kb/s total
> ---------------------------------------------------------------
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: httpclient-users-unsubscribe@hc.apache.org
> For additional commands, e-mail: httpclient-users-help@hc.apache.org
>
>

Re: Socket leak of Async HTTP server

Posted by Oleg Kalnichevski <ol...@apache.org>.
On Sun, 2012-12-16 at 13:03 +0200, Nir Dweck wrote:
> 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

Nir

Your code does not compile so I cannot test it. I know that HttpCore
(both blocking and non-blocking) can easily handle millions of requests.
There is an (non-scientific) HTTP micro-benchmark used by the project to
test HttpCore's performance [1]. Based on it 1'000'000 request do not
seem to pose any sort of issue.

Feel free to tweak the micro-benchmark and see how it performs for you

Oleg

[1]
http://svn.apache.org/repos/asf/httpcomponents/benchmark/httpcore/trunk/

---------------------------------------------------------------
HttpCore (blocking I/O); version: 4.2.3
---------------------------------------------------------------

Server Software:		HttpCore-Test/1.1
Server Hostname:		localhost
Server Port:			8989

Document Path:			http://localhost:8989/rnd?c=2048
Document Length:		2048 bytes

Concurrency Level:		10
Time taken for tests:		9.889423 seconds
Complete requests:		1000000
Failed requests:		0
Write errors:			0
Kept alive:			1000000
Total transferred:		2048000000 bytes
Requests per second:		101,118.13 [#/sec] (mean)
Time per request:		0.099 [ms] (mean)
Time per request:		0.010 [ms] (mean, across all concurrent requests)
Transfer rate:			207,089.94 [Kbytes/sec] received
				-1 kb/s sent
				207,089.94 kb/s total
---------------------------------------------------------------
---------------------------------------------------------------
HttpCore (NIO); version: 4.2.3
---------------------------------------------------------------

Server Software:		HttpCore-NIO-Test/1.1
Server Hostname:		localhost
Server Port:			8989

Document Path:			http://localhost:8989/rnd?c=2048
Document Length:		2048 bytes

Concurrency Level:		10
Time taken for tests:		20.235072 seconds
Complete requests:		1000000
Failed requests:		0
Write errors:			0
Kept alive:			1000000
Total transferred:		2048000000 bytes
Requests per second:		49,419.15 [#/sec] (mean)
Time per request:		0.202 [ms] (mean)
Time per request:		0.020 [ms] (mean, across all concurrent requests)
Transfer rate:			101,210.41 [Kbytes/sec] received
				-1 kb/s sent
				101,210.41 kb/s total
---------------------------------------------------------------   


---------------------------------------------------------------------
To unsubscribe, e-mail: httpclient-users-unsubscribe@hc.apache.org
For additional commands, e-mail: httpclient-users-help@hc.apache.org