hc-httpclient-users mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From "Francesco Toro XB" <francesco.xb.t...@ericsson.com>
Subject HTTPCORE memory leak on simple server implementation
Date Mon, 15 Feb 2010 15:52:21 GMT
Hi All,

I'm trying using HttpCore to build a simple HttpServer. 
My Server must receive http requests (only "POST" method supported) with
xml body of more or less 22 Mbyte.

As first instance I used the ElementalHttpServer.java as reference with
little modification.

When I start the server on Solaris platform and I start sending on it,
with a remote httpClient, the http requests,  this is the output I can
see:

>java -cp ./httpServerExample.jar:./httpcore-4.0.1.jar:
ElementalHttpServer
Listening on port 21000

Incoming connection from /10.10.10.176
New connection thread
Incoming entity content (bytes): 29155635
Client closed connection

Looking at the memory with "prstat" I can observe that it increase
without release the resource allocated. It increase for each message the
http Server receive.
After the first http request it increase from 30M to 86M, after the
second from 86M to 142M, then raise up to 199M....until a java heap
exception is raised.
The incoming request throughput is quite low (1 message every 10
seconds) 

This is the "prstat" output:


>ps -aef | grep http
    user 27699    61   0 16:13:23 pts/8       0:00 grep http
    user 27691  7871   0 16:12:37 pts/5       0:01 java -cp
./httpServerExample.jar:./commons-httpcore.jar ElementalHttpServer
imssrv83(aomp) /home/aomp/lib>prstat | grep 27691
 27691 aomp      172M   30M sleep   59    0   0:00:00 0.0% java/24
 27691 aomp      172M   86M sleep   59    0   0:00:02 0.1% java/24
 27691 aomp      172M   86M sleep   59    0   0:00:02 0.1% java/24
 27691 aomp      172M   86M sleep   59    0   0:00:02 0.1% java/24
 27691 aomp      172M   86M sleep   59    0   0:00:02 0.0% java/24
 27691 aomp      172M   86M sleep   59    0   0:00:02 0.0% java/24
 27691 aomp      172M   86M sleep   59    0   0:00:02 0.0% java/24
 27691 aomp      172M   86M sleep   59    0   0:00:02 0.0% java/24
 27691 aomp      172M   86M sleep   59    0   0:00:02 0.0% java/24
 27691 aomp      172M   86M sleep   59    0   0:00:02 0.0% java/24
 27691 aomp      172M   86M sleep   59    0   0:00:02 0.0% java/24
 27691 aomp      172M   86M sleep   59    0   0:00:02 0.0% java/24
 27691 aomp      172M   86M sleep   59    0   0:00:02 0.0% java/24
 27691 aomp      172M   86M sleep   59    0   0:00:02 0.0% java/24
 27691 aomp      172M   86M sleep   59    0   0:00:02 0.0% java/24
 27691 aomp      172M  102M cpu1    39    0   0:00:02 0.0% java/25
 27691 aomp      172M  142M sleep   59    0   0:00:03 0.0% java/24
 27691 aomp      172M  142M sleep   59    0   0:00:03 0.0% java/24
 27691 aomp      172M  142M sleep   59    0   0:00:03 0.0% java/24
 27691 aomp      172M  142M sleep   59    0   0:00:03 0.0% java/24
 27691 aomp      172M  142M sleep   59    0   0:00:03 0.0% java/24
 27691 aomp      172M  142M sleep   59    0   0:00:03 0.0% java/24
 27691 aomp      172M  142M sleep   59    0   0:00:03 0.0% java/24
 27691 aomp      172M  142M sleep   59    0   0:00:03 0.0% java/24
 27691 aomp      172M  142M sleep   59    0   0:00:03 0.0% java/24
 27691 aomp      172M  142M sleep   59    0   0:00:03 0.0% java/24
 27691 aomp      172M  142M sleep   59    0   0:00:03 0.0% java/24
 27691 aomp      172M  142M sleep   59    0   0:00:03 0.0% java/24
 27691 aomp      172M  142M sleep   59    0   0:00:03 0.0% java/24
 27691 aomp      200M  170M cpu12   28    0   0:00:04 0.3% java/25
 27691 aomp      228M  199M sleep   59    0   0:00:04 0.1% java/24
 27691 aomp      228M  199M sleep   59    0   0:00:04 0.1% java/24

 27691 aomp      228M  199M sleep   59    0   0:00:04 0.0% java/24
 27691 aomp      228M  199M sleep   59    0   0:00:04 0.0% java/24
 27691 aomp      228M  199M sleep   59    0   0:00:04 0.0% java/24
 27691 aomp      228M  199M sleep   59    0   0:00:04 0.0% java/24
 27691 aomp      228M  199M sleep   59    0   0:00:04 0.0% java/24
 27691 aomp      228M  199M sleep   59    0   0:00:04 0.0% java/24


This is the http server java code I'm testing.

import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Locale;

import org.apache.http.ConnectionClosedException;
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.HttpServerConnection;
import org.apache.http.MethodNotSupportedException;
import org.apache.http.impl.DefaultConnectionReuseStrategy;
import org.apache.http.impl.DefaultHttpResponseFactory;
import org.apache.http.impl.DefaultHttpServerConnection;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.CoreProtocolPNames;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.BasicHttpContext;
import org.apache.http.protocol.BasicHttpProcessor;
import org.apache.http.protocol.HttpContext;
import org.apache.http.protocol.HttpRequestHandler;
import org.apache.http.protocol.HttpRequestHandlerRegistry;
import org.apache.http.protocol.HttpService;
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.http.util.EntityUtils;

/**
 * Basic, yet fully functional and spec compliant, HTTP/1.1 file server.
 * <p>
 * Please note the purpose of this application is demonstrate the usage
of HttpCore APIs.
 * It is NOT intended to demonstrate the most efficient way of building
an HTTP file server. 
 * 
 *
 * @version $Revision: 744516 $
 */
public class ElementalHttpServer {

    public static void main(String[] args) throws Exception {

        Thread t = new RequestListenerThread(21000);
        t.setDaemon(false);
        t.start();
    }
    
    static class HttpFileHandler implements HttpRequestHandler  {
        
        public HttpFileHandler() {
            super();
        }
        
        public void handle(
                final HttpRequest request, 
                final HttpResponse response,
                final HttpContext context) throws HttpException,
IOException {

            String method =
request.getRequestLine().getMethod().toUpperCase(Locale.ENGLISH);
            if (!method.equals("POST")) {
                throw new MethodNotSupportedException(method + " method
not supported"); 
            }

            if (request instanceof HttpEntityEnclosingRequest) {
                HttpEntity entity = ((HttpEntityEnclosingRequest)
request).getEntity();
                byte[] entityContent = EntityUtils.toByteArray(entity);
                System.out.println("Incoming entity content (bytes): " +
entityContent.length);
                entity.consumeContent();
            }

        }
        
    }
    
    static class RequestListenerThread extends Thread {

        private final ServerSocket serversocket;
        private final HttpParams params; 
        private final HttpService httpService;
        
        public RequestListenerThread(int port) throws IOException {
            this.serversocket = new ServerSocket(port);
            this.params = new BasicHttpParams();
            this.params
                .setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000)
 
.setIntParameter(CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024)
 
.setBooleanParameter(CoreConnectionPNames.STALE_CONNECTION_CHECK, false)
                .setBooleanParameter(CoreConnectionPNames.TCP_NODELAY,
true)
                .setParameter(CoreProtocolPNames.ORIGIN_SERVER,
"HttpComponents/1.1");

            // Set up the HTTP protocol processor
            BasicHttpProcessor httpproc = new BasicHttpProcessor();
            httpproc.addInterceptor(new ResponseDate());
            httpproc.addInterceptor(new ResponseServer());
            httpproc.addInterceptor(new ResponseContent());
            httpproc.addInterceptor(new ResponseConnControl());
            
            // Set up request handlers
            HttpRequestHandlerRegistry reqistry = new
HttpRequestHandlerRegistry();
            reqistry.register("*", new HttpFileHandler());
            
            // Set up the HTTP service
            this.httpService = new HttpService(
                    httpproc, 
                    new DefaultConnectionReuseStrategy(), 
                    new DefaultHttpResponseFactory());
            this.httpService.setParams(this.params);
            this.httpService.setHandlerResolver(reqistry);
        }
        
        public void run() {
            System.out.println("Listening on port " +
this.serversocket.getLocalPort());
            while (!Thread.interrupted()) {
                try {
                    // Set up HTTP connection
                    Socket socket = this.serversocket.accept();
                    DefaultHttpServerConnection conn = new
DefaultHttpServerConnection();
                    System.out.println("Incoming connection from " +
socket.getInetAddress());
                    conn.bind(socket, this.params);

                    // Start worker thread
                    Thread t = new WorkerThread(this.httpService, conn);
                    t.setDaemon(true);
                    t.start();
                } catch (InterruptedIOException ex) {
                    break;
                } catch (IOException e) {
                    System.err.println("I/O error initialising
connection thread: " 
                            + e.getMessage());
                    break;
                }
            }
        }
    }
    
    static class WorkerThread extends Thread {

        private final HttpService httpservice;
        private final HttpServerConnection conn;
        
        public WorkerThread(
                final HttpService httpservice, 
                final HttpServerConnection conn) {
            super();
            this.httpservice = httpservice;
            this.conn = conn;
        }
        
        public void run() {
            System.out.println("New connection thread");
            HttpContext context = new BasicHttpContext(null);
            try {
                while (!Thread.interrupted() && this.conn.isOpen()) {
                    this.httpservice.handleRequest(this.conn, context);
                }
            } catch (ConnectionClosedException ex) {
                System.err.println("Client closed connection");
            } catch (IOException ex) {
                System.err.println("I/O error: " + ex.getMessage());
            } catch (HttpException ex) {
                System.err.println("Unrecoverable HTTP protocol
violation: " + ex.getMessage());
            } finally {
                try {
                    this.conn.shutdown();
                } catch (IOException ignore) {}
            }
        }

    }
    
}


How can i avoid this memory behaviour?

Thanks a lot,

Francesco.




Mime
  • Unnamed multipart/alternative (inline, None, 0 bytes)
View raw message