I am using Restlet to implement a web service. The client (also uses Restlet) makes many consecutive calls to the server, but after a small number of calls complete successfully, further calls hang the server, which shows the message:
INFO: Stop accepting new connections and transactions. Consider increasing the maximum number of threads.
I tried:
getContext().getParameters().add("maxThreads", "200");
but that does not help. In any case, it seems like the client should be able to make an unlimited number of calls, and increasing maxThreads just ups the limit. It looks like I am not freeing up some resource or disconnecting after each client call, but I do not know how to do so.
The following (small as I could make it) stand alone program demonstrates the problem. It starts a simple server and then a client calls it a bunch of times:
/** You may copy, modify, and re-use this code as you see fit - Jim Irrer */
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.restlet.Application;
import org.restlet.Component;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.Restlet;
import org.restlet.Server;
import org.restlet.data.MediaType;
import org.restlet.data.Method;
import org.restlet.data.Protocol;
import org.restlet.data.Status;
import org.restlet.representation.InputRepresentation;
import org.restlet.representation.Representation;
import org.restlet.resource.ClientResource;
import org.restlet.resource.Directory;
public class SimpleServerPut extends Component implements Runnable {
private static final int PORT = 8080;
private static int readToByteArray(InputStream inputStream, byte[] buf) throws IOException {
int length = 0;
int b;
while ((b = inputStream.read()) != -1) {
buf[length++] = (byte)b;
}
return length;
}
@Override
public void run() {
getContext().getParameters().add("maxThreads", "200");
// Create the HTTP server and listen on port PORT
SimpleServerPut simpleServer = new SimpleServerPut();
Server server = new Server(Protocol.HTTP, PORT, simpleServer);
simpleServer.getClients().add(Protocol.FILE);
// Create an application
Application application = new Application(simpleServer.getContext()) {
@Override
public Restlet createRoot() {
return new Directory(getContext(), "C:");
}
};
// Attach the application to the component and start it
simpleServer.getDefaultHost().attach("/stuff/", application);
try {
server.start();
}
catch (Exception ex) {
ex.printStackTrace();
}
}
@Override
public void handle(Request request, Response response) {
// assume the worst
response.setStatus(Status.CLIENT_ERROR_METHOD_NOT_ALLOWED);
response.setEntity("No no - Bad client! Only do PUTs.", MediaType.TEXT_PLAIN);
try {
if (request.getMethod() == Method.PUT) {
InputStream inputStream = request.getEntity().getStream();
byte[] buf = new byte[64*1024];
int totalLength = readToByteArray(inputStream, buf);
response.setStatus(Status.SUCCESS_OK);
String msg = "Number of bytes received: " + totalLength;
response.setEntity(msg, MediaType.TEXT_PLAIN);
System.out.println("server: " + msg);
return;
}
}
catch (Exception ex) {
ex.printStackTrace();
}
}
private static String callServer() throws IOException {
String urlText = "http://localhost:" + PORT + "/";
ClientResource clientResource = new ClientResource(urlText);
clientResource.setReferrerRef(urlText);
byte[] buf = new byte[1000];
for (int i = 0; i < buf.length; i++) {
buf[i] = (byte)((int)'a' + (i%26));
}
ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(buf);
Representation representation = new InputRepresentation(byteArrayInputStream, MediaType.APPLICATION_OCTET_STREAM);
Representation representation2 = clientResource.put(representation);
byte[] responseBuf = new byte[16*1024];
int length = readToByteArray(representation2.getStream(), responseBuf);
Response response = clientResource.getResponse();
Status status = response.getStatus();
return "status: " + status + " message: " + new String(responseBuf, 0, length);
}
// Start server and call it a bunch of times
public static void main(String[] args) throws Exception {
SimpleServerPut simpleServer = new SimpleServerPut();
new Thread(simpleServer).start();
Thread.sleep(200); // cheap trick to make sure that server is running
// make a bunch of client calls
for (int t = 0; t < 100; t++) {
System.out.println("client count: " + (t+1) + " " + callServer());
}
System.exit(0);
}
}
We were only able to solve the problem by stopping the ClientResource's associated client directly (using Restlet version 2.0.15):
Client c = (Client)clientResource.getNext();
try {
c.stop();
} catch (Exception e) {
//handle exception
}
Add a line so that the client releases the resource:
Response response = clientResource.getResponse();
Status status = response.getStatus();
clientResource.release(); // add this line
to the client and everything works. Eventually the server times out if the client dies, but that takes a while.
I've solved my problem downloading the last stable release of the Restlet API
Apparently the .jar the I've been using were an old version where the release()
command doesn't make any effect.
Before the update the client log only outputs the start of the client:
Sep 05, 2012 9:50:19 AM org.restlet.engine.http.connector.HttpClientHelper start
INFO: Starting the default HTTP client
Now it are outputing the stop too:
Sep 05, 2012 9:50:19 AM org.restlet.engine.http.connector.HttpClientHelper stop
INFO: Stopping the default HTTP client
In addition to calling ClientResource.release(), you may want to call exhaust() on the representation.
Representation responseRepresentation = response.getEntity();
if (responseRepresentation != null) {
try {
responseRepresentation.exhaust();
} catch (IOException e) {
// handle exception
}
responseRepresentation.release();
}
Related discussion in this thread .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.