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.